从 redux 中的 reducer 取回 ID

IT技术 javascript reactjs redux react-redux redux-thunk
2021-05-03 19:37:32

我是新手,正在尝试使用 react & redux 构建一个简单的书签应用程序。

我无法解决这个问题:

用户可以创建一个书签并将其添加到多个文件夹中所以我调度一个addMark(bookmark)动作,然后addMark(folder)或者editFolder(folder)如果文件夹已经存在。如您所见,书签和文件夹是通过相同的操作添加的,因为在我的状态树中,它们都只是标记- 由它们的类型属性区分。

我的问题:如何告诉文件夹对象哪个是要添加到文件夹书签列表的新书签?如何在两次调度之间检索新创建的书签的 ID?

我不满意的解决方案:

  1. 我知道如何在减速器中生成Math.max书签 ID (通过现有的书签 ID),所以我可以在 2 个分派之间复制新的书签 ID。这听起来像是一个糟糕的黑客。
  2. 书签和文件夹保存在同一个状态分支(同一个减速器)中,因为它们都只是“标记”,我可以有一个引用最新添加的书签的状态属性,但这听起来也像一个糟糕的黑客。

一点源代码,了解我所拥有的:

// mapping between dispatcher and props to my react view
const mapDispatchToProps = (dispatch) => ({
  saveMark: (mark) => {
    if (mark.id) {
      dispatch(editMark(mark));
    } else {
      dispatch(addMark(mark));
    }
  },
});
export default connect(mapStateToProps, mapDispatchToProps)(AddMark);

还有里面的AddMark,也就是容器组件:

// save the bookmark first
this.props.saveMark({
      type: 'bookmark',
      title: this.state.title,
      url: this.state.url,
      icon: this.props.icon,
      style: this.state.style,
 });
 // now I need the bookmark ID
 folders.forEach(folder => {
    folder.children.push(bookmarkID) // <-- !!!
 });
 folders.forEach(folder => this.props.saveMark(folder));

我无法为此找到令人满意的解决方案。

2个回答

我认为你应该在这里只发送一个 action: addBookmark(),它接受书签对象和文件夹。

您处理将书签对象添加到文件夹的代码应该是 reducer 的一部分。

另外,请参考Redux 项目中Todos 示例它在动作创建中提供了 id,以便在组件中读取它。您还可以使用当前状态来计算最新的 id:

function addBookmark(bookmark, folder) {
   return (dispatch, getState) => {
       const newBookmark = Object.assign({
         id: Math.max(0, ...getState().bookmarks.map(b => b.id)) + 1,
       }, bookmark);
       dispatch({
         type: 'ADD_BOOKMARK',
         bookmark: newBookmark,
         folder: folder
       });
   }
}

请注意,示例需要redux-thunk中间件来分派这些操作。

然后你可以在文件夹 reducer 中访问带有 id 的书签

function folderReducer(state = [], action) {
  if(action.type === 'ADD_BOOKMARK') {
     return state.map(folder => {
       if(folder === action.folder) {
         return Object.assign({}, folder, {children: [...folder.children, action.bookmark.id]}
       }
       return folder;
     })
  }
  //another reducer code
  return state;
} 

Reducers 只是在操作您商店的实例。您可以使用getState() 获取状态的当前快照