这是我参与「 第四届青训营 」笔记创作活动的第五天
React是单向数据流还是双向数据流?
React 是自顶向下的单向数据流:数据只有一种方式可以传输到应用程序的其他部分(数据不能以相反的方式流动)。
状态始终由一个组件拥有,受此状态影响的任何数据只能影响其下的子组件。(更改状态永远不会影响其父代及兄弟组件,只影响其子代)
- 状态传递给视图和子组件
- 操作由视图触发
- 动作可以更新状态
- 状态更改将传递到视图和子组件
数据单向流动的优点:
- 所有状态的改变可记录、可追踪,源头易追溯;
- 所有数据只有一份,组件数据只有唯一的入口和出口
- 有利于程序维护,保证数据的可控性
vue 和 react 的单向数据流
虽然 vue 有双向绑定 v-model,但是 vue 和 react 父子组件之间的数据传输,仍然还是遵循单向数据流的,父组件可以向子组件传递 props,但是子组件不能修改父组件传递来的 props,子组件只能通知父组件进行数据更改
状态管理之 setState 的同步和异步问题
- setState 会将多个调用合并为一个来执行(队列机制)
- render() 中不要调用 setState 方法,会发生死循环
- setState 本身的执行过程和代码是同步的,只是它在合并数据与钩子函数的调用顺序在更新后无法拿到值,形成了异步,我们可以通过第二个参数拿到更新后的结果
//当执行到 setState 时,React 出于性能考虑,并不会立马执行修改 state ,而是先把当前更新对象以及后续的合并到一起,放在一个更新队列里进行合并操作,这期间并不会影响后续代码执行。且多次调用会合并,以最后一次渲染为主,以此来进行性能优化
changeText() {
this.setState({
age: 20
}, () => {
console.log(this.state.age); // 文本已经被改变,得到的是20
});
}
也可以通过钩子函数获取修改后的值
componentDidUpdate() {
console.log(this.state.age);
}
‘ 同步 ’
- 在
setTimeout / setInterval或者原生事件(比如点击事件等)的回调中,或者是在 setState 前面遇到 await 后续表现都是同步的 - 当遇到 Promise.thenn(fn) / fetch 回调 / xhr 网络回调时,表现为同步的
‘ 异步 ’
- 一般情况下(常见在生命周期或者是合成事件处理函数中),通过 setState() 方法来更新状态的,表现是异步的
状态管理之 render() 触发时机
- 组件初始化的时候
- 类组件执行了 setState,此时无论 state 是否发生了变化,该组件都将被重新渲染
- 父组件重新渲染了,子组件也会重新渲染
- 函数组件使用 useState 更改状态不一定导致重新 render,只有 state 发生变化了才会执行 render
- 组件的 props 改变了,不一定触发 render 的执行,但是如果 props 的值来自于父组件或者祖先组件的 state,这种情况下只要父组件或者祖先组件的 state 发生变化,子组件就会重新 render