之前在做项目的过程中,曾遇到这样一个问题(如题):在 reducer 中更新了 state,而页面却没有刷新,这是为什么呢?遵循 30 min 自己解决不了就问老师的原则,于是就有了下面的对话:
某同学:老师,我们在做 *** 的时候,可以在控制台看到 next State 里面的数据更新了,但是页面却没有更新。 ...
几分钟后,还不等老师回复,这个问题已经解决了,于是有了下面的对话
某同学:老师这个问题我们现在解决了。 老师:说说 某同学:因为在 reducer 里面要返回新数组,及时我在当前 data 已经被改变,也不能直接返回。 老师:是这样的 某同学:但是我有一个疑问,如果是这个环节出问题,为什么我在控制台 的next state 可以看到数据发生变化 老师:不是不能返回,是 redux 会判断两个对象是否一样 某同学:如果是同一个对象就不会更新 state 老师:State 会被更新,组件不一定更新。
听到这里,不知道你有没有疑问,总之我是有很大的疑问:
我:为什么组件不一定跟新 老师:为什么要更新呢 我:之前不都是,更新了 state 然后会用新的 state 去渲染页面,这里的 state 更新了,那就是用新的 state 渲染页面 老师:你说的是 set state 吗 我:是 老师:你的问题是什么 我:你刚说 state 更新了,组件不一定更新,然后,我问的是,为什么组件不一定更新 老师:我说的 state 是哪里的 state 我:reducer 老师:你说的 state 又是哪里的 ...
可能听到以上这些对话,对于 state 更新了,组件却没有更新这个问题,还处于懵逼之中,那么就由我细细说来。
最开始我们写的 reducer 的代码是这样的:
const editHomework = (data, newQuizzes) => {
const sectionIndex = newQuizzes.sectionIndex;
let rowSection = data.sections.filter(section => section.type === 'homeworkQuiz');
let quizzes = rowSection[sectionIndex].quizzes.concat(newQuizzes.quizzes);
rowSection[sectionIndex].quizzes = quizzes;
return data;
};
而当我们将上面这段代码改成下面这样,就会达到我们期望的效果:
const editHomework = (data, newQuizzes) => {
let newData = Object.assign({}, data);
const sectionIndex = newQuizzes.sectionIndex;
let rowSection = newData.sections.filter(section => section.type === 'homeworkQuiz');
let quizzes = rowSection[sectionIndex].quizzes.concat(newQuizzes.quizzes);
rowSection[sectionIndex].quizzes = quizzes; return newData;
};
这是为什么呢?
首先,reducer 中的 state 是引用,在此处对 state 进行修改,store 内部的 state 同样也就改变了。然而,react - redux 认为 dispatch 前后的 state 没有改变,就不会重新渲染页面,实际上 state 已经改变了。
结果往往就是这么简单,然而要想进一步理解这其中的原由,还得多看 源码 。
为了避免以上问题的发生,谨记 不要直接修改 state,不要直接修改 state ,不要直接修改 state。
详情见 文档