Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将减速器和动作绑定到非根组件_Javascript_Reactjs_Redux_React Redux - Fatal编程技术网

Javascript 将减速器和动作绑定到非根组件

Javascript 将减速器和动作绑定到非根组件,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,背景 我在Angular 1.x上有一年半的工作经验,正在为Angular不适合的项目进行React/Redux。我在某个地方读到过React是Angular的“基本上所有指令”,这很奇妙,因为我认为指令是Angular最强大的功能。然而,在React/Redux中创建应用程序的想法与Angular的想法也有很大不同(比如创建数据主干然后表示它的想法,与Angular的不太集中的方法不同)。有些事情我很难理解 设置 应用程序正在以电子形式编写,使用以下内容作为树苗: 我的根减速器看起来像这样:

背景

我在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中使用一个不同的模式,那你就真的违反了规则