背景
我在 Angular 1.x 方面有一年半的经验,在 Angular 不适合的项目中转向 React/Redux。我在某处读到过,React 是“基本上所有指令”都来自 Angular,这太棒了,因为我认为指令是 Angular 最强的功能。然而,在 React/Redux 中创建应用程序的心态与 Angular 也非常不同(比如创建数据主干然后表示它的想法,与 Angular 不太集中的方法相比)。有件事我很难理解。
设置
该应用程序是用 Electron 编写的,使用以下内容作为树苗:https://github.com/chentsulin/electron-react-boilerplate
我的根 reducer 看起来像这样:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
图库有打开目录的功能。它扫描用户选择的目录并在那里查找照片,接收文件名数组。然后,它应该将每张照片渲染为一个组件,并且每张照片在使用文件名初始化后,应该启动自己的读取图片元数据并在页面上渲染自己的信息的过程。
我已经可以毫无问题地渲染页面上的所有文件名了。但是,我需要将文件名转换为渲染和处理的照片。这就是我遇到麻烦的地方。
问题
这张照片有一些属性,如上面的内容所示。它还具有一些操作(例如,new
、update
、delete
等)。属性和操作需要与组件绑定(bind)。通常,对于页面大小的组件,这是在 JS 文件中完成的,该文件执行所有 connect
和 bindActionCreators
调用。然后这个 JS 文件被包含在 React 路由器中,并以页面的形式呈现。
照片不是页面。它们是可重用的组件,页面上有很多这些组件。如何正确地将照片的所有属性和操作附加到它?
最佳答案
看起来你的模型/ Action / reducer 上的电线可能交叉了。与 Angular 和其他框架不同,您的模型应该是“愚蠢的”,因为它只是数据;您的 Gallery
或 Photo
对象不应具有方法。相反,您的 View 触发操作,您的 reducer 使用这些操作来更新存储(保存模型),然后读取该存储并将其推回到 View 中。与 MVVM(MVV*?)不同,您的模型(存储状态)不必模仿组件的结构;相反,它只是维护纯数据。因此,拥有 Home
和 Gallery
属性可能没有意义。
让我们像这样重新想象你的 reducer :
const initialState = {
photos: []
};
export default function reducer(state = initialState, action) {
switch (action.type) {
case 'DELETE_PHOTO':
return {
photos: state.photos.filter(photo => photo.filename !== action.payload.filename)
};
// etc.
}
return state;
}
现在你的 View 可能是这样的:
import deletePhoto from '../actionCreators/deletePhoto';
function Photo({ filename, onDelete }) {
return (
<div>
<img src={filename}/>
<button onClick={() => onDelete(filename)}>Delete</button>
</div>
);
}
function PhotoGallery({ photos, deletePhoto }) {
return (
<div>
{
photos.map(photo => <Photo filename={photo.filename} onDelete={deletePhoto}/>);
}
</div>
);
};
const mapStateToProps = state => ({ photos: state.photos });
const mapActionsToProps = { deletePhoto };
export default connect(mapStateToProps, mapActionsToProps)(PhotoGallery);
...那么你的 Action 创建者deletePhoto
可能是这样的:
export default function deletePhoto(filename) {
return { type: 'DELETE_PHOTO', payload: { filename } };
}
建议将您的 reducer 分解为更细粒度的部分,但您可以使用 combineReducers 之类的东西,而不是通过增强模型来实现这一点。 .
我建议你尝试忘记 MVVM 并真正理解 Flux 模式。我并不是说这是一个更好的模式,但如果您尝试在 redux 中使用不同的模式,那么您确实会违背常规。
关于javascript - 将 reducer 和操作绑定(bind)到非根组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39239253/