Javascript 将减速器和动作绑定到非根组件
背景 我在Angular 1.x上有一年半的工作经验,正在为Angular不适合的项目进行React/Redux。我在某个地方读到过React是Angular的“基本上所有指令”,这很奇妙,因为我认为指令是Angular最强大的功能。然而,在React/Redux中创建应用程序的想法与Angular的想法也有很大不同(比如创建数据主干然后表示它的想法,与Angular的不太集中的方法不同)。有些事情我很难理解 设置 应用程序正在以电子形式编写,使用以下内容作为树苗: 我的根减速器看起来像这样:Javascript 将减速器和动作绑定到非根组件,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,背景 我在Angular 1.x上有一年半的工作经验,正在为Angular不适合的项目进行React/Redux。我在某个地方读到过React是Angular的“基本上所有指令”,这很奇妙,因为我认为指令是Angular最强大的功能。然而,在React/Redux中创建应用程序的想法与Angular的想法也有很大不同(比如创建数据主干然后表示它的想法,与Angular的不太集中的方法不同)。有些事情我很难理解 设置 应用程序正在以电子形式编写,使用以下内容作为树苗: 我的根减速器看起来像这样:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
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;
}
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);
“多媒体资料”具有打开目录的功能。它扫描用户选择的目录并在那里查找照片,同时接收一组文件名。然后,它应该将每个照片作为一个组件进行渲染,并且在使用文件名初始化后,每个照片都应该启动自己的进程,读取图片元数据并在页面上呈现自己的信息
我已经达到了可以呈现页面上所有文件名的程度,没有问题。但是,我需要将文件名转换为渲染和处理的照片。这就是我遇到麻烦的地方
问题
这张照片有一些特性,如上面的一点所示。它还有一些操作(例如,新建
,更新
,删除
,等等)。属性和操作需要绑定到组件。通常,对于页面大小的组件,这是在一个JS文件中完成的,该文件执行所有connect
和bindActionCreators
调用。这个JS文件随后被包含在react路由器中,并以页面的形式呈现
照片不是网页。它们是可重用的组件,页面上有很多。如何正确地将照片的所有属性和动作附加到照片上?看起来您可能在模型/动作/减速器上遇到了问题。与Angular和其他框架不同,您的模型应该是“愚蠢的”,因为它只是数据;您的
图库
或照片
对象不应具有方法。相反,视图触发操作,reducer使用这些操作更新存储(保存模型),然后读取存储并将其推回到视图中。与MVVM(MVV*?)不同,您的模型(存储状态)不必模仿组件的结构;相反,它只维护纯数据。因此,拥有主页
和图库
属性可能没有意义
让我们像这样重新想象你的减速器:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
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;
}
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);
现在,您的观点可能是这样的:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
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;
}
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);
建议将减速器分解为更细粒度的部件,但不要通过增加模型来实现这一点,您可以使用类似的方法
我建议你试着忘掉MVVM,真正理解流量模式。我并不是说这是一个更好的模式,但如果你尝试在redux中使用不同的模式,那你就真的违反了规则。看起来你可能在模型/动作/减速器上遇到了问题。与Angular和其他框架不同,您的模型应该是“愚蠢的”,因为它只是数据;您的
图库
或照片
对象不应具有方法。相反,视图触发操作,reducer使用这些操作更新存储(保存模型),然后读取存储并将其推回到视图中。与MVVM(MVV*?)不同,您的模型(存储状态)不必模仿组件的结构;相反,它只维护纯数据。因此,拥有主页
和图库
属性可能没有意义
让我们像这样重新想象你的减速器:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
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;
}
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);
现在,您的观点可能是这样的:
root: {
Home: Object, // Basic homepage tab
Gallery: [ // Gallery tab
{ // A single instance of "photo" object
filename: String,
metadata: Object,
error: Object
}
]
}
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;
}
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);
建议将减速器分解为更细粒度的部件,但不要通过增加模型来实现这一点,您可以使用类似的方法
我建议你试着忘掉MVVM,真正理解流量模式。我并不是说这是一个更好的模式,但是如果你尝试在redux中使用一个不同的模式,那你就真的违反了规则