大家可以在第二阶段的代码上进行修改 comment-app2(非高阶组件版本)。如果已经忘了第二阶段评论功能的同学可以先简单回顾一下它的功能需求,。第一、二、三阶段的实战代码都可以在这里找到:react-naive-book-examples

    我们首先安装好依赖,现在 comment-app2 需要依赖 Redux、React-redux 了,进入工程目录执行命令安装依赖:

    然后我们二话不说先在 下建立三个空目录:componentscontainersreducers

    我们之前的 reducer 都是直接写在 src/index.js 文件里面,这是一个不好的做法。因为随着应用越来越复杂,可能需要更多的 reducer 来帮助我们管理应用(这里后面的章节会有所提及)。所以最好还是把所有 reducer 抽出来放在一个目录下 src/reducers

    对于评论功能其实还是比较简单的,回顾一下我们在章节里面不断提升的状态是什么?其实评论功能的组件之间共享的状态只有 comments。我们可以直接只在 src/reducers 新建一个 reducer comments.js 来对它进行管理。

    1. // action types
    2. const INIT_COMMENTS = 'INIT_COMMENTS'

    我们用三个常量来存储 action.type 的类型,这样以后我们修改起来就会更方便一些。根据这三个操作编写 reducer:

    我们只存储了一个 comments 的状态,初始化为空数组。当遇到 INIT_COMMENTS 的 action 的时候,会新建一个对象,然后用 action.comments 覆盖里面的 comments 属性。这就是初始化评论操作。

    同样新建评论操作 ADD_COMMENT 也会新建一个对象,然后新建一个数组,接着把原来 state.comments 里面的内容全部拷贝到新的数组当中,最后在新的数组后面追加 action.comment。这样就相当新的数组会比原来的多一条评论。(这里不要担心数组拷贝的性能问题,[…state.comments] 是浅拷贝,它们拷贝的都是对象引用而已。)

    对于删除评论,其实我们需要做的是新建一个删除了特定下标的内容的数组。我们知道数组 会根据你传进去的下标拷贝特定范围的内容放到新数组里面。所以我们可以利用 slice 把原来评论数组中 action.commentIndex 下标之前的内容拷贝到一个数组当中,把 action.commentIndex 坐标之后到内容拷贝到另外一个数组当中。然后把两个数组合并起,就相当于“删除”了 action.commentIndex 的评论了。

    这样就写好了评论相关的 reducer。

    action creators

    1. dispatch({ type: 'INIT_COMMENTS', comments })

    每次都要写 type 其实挺麻烦的,而且还要去记忆 action type 的名字也是一种负担。我们可以把 action 封装到一种函数里面,让它们去帮助我们去构建这种 action,我们把它叫做 action creators。

    所谓 action creators 其实就是返回 action 的函数,这样我们 dispatch 的时候只需要传入数据就可以了:

    1. dispatch(initComments(comments))

    action creators 还有额外好处就是可以帮助我们对传入的数据做统一的处理;而且有了 action creators,代码测试起来会更方便一些。这些内容大家可以后续在实际项目当中进行体会。

    整个 src/reducers/comments.js 的代码就是:

    • 定义 action types
    • 跟这个 reducer 相关的 action creators