React 数据传输与状态管理 | 青训营笔记

148 阅读3分钟

这是我参与「 第四届青训营 」笔记创作活动的第五天

React是单向数据流还是双向数据流?

React 是自顶向下的单向数据流:数据只有一种方式可以传输到应用程序的其他部分(数据不能以相反的方式流动)。
状态始终由一个组件拥有,受此状态影响的任何数据只能影响其下的子组件。(更改状态永远不会影响其父代及兄弟组件,只影响其子代)

  • 状态传递给视图和子组件
  • 操作由视图触发
  • 动作可以更新状态
  • 状态更改将传递到视图和子组件

image.png

数据单向流动的优点:

  1. 所有状态的改变可记录、可追踪,源头易追溯;
  2. 所有数据只有一份,组件数据只有唯一的入口和出口
  3. 有利于程序维护,保证数据的可控性

vue 和 react 的单向数据流

虽然 vue 有双向绑定 v-model,但是 vue 和 react 父子组件之间的数据传输,仍然还是遵循单向数据流的,父组件可以向子组件传递 props,但是子组件不能修改父组件传递来的 props,子组件只能通知父组件进行数据更改

image.png

状态管理之 setState 的同步和异步问题

  1. setState 会将多个调用合并为一个来执行(队列机制)
  2. render() 中不要调用 setState 方法,会发生死循环
  3. 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() 触发时机

  1. 组件初始化的时候
  2. 类组件执行了 setState,此时无论 state 是否发生了变化,该组件都将被重新渲染
  3. 父组件重新渲染了,子组件也会重新渲染
  4. 函数组件使用 useState 更改状态不一定导致重新 render,只有 state 发生变化了才会执行 render
  5. 组件的 props 改变了,不一定触发 render 的执行,但是如果 props 的值来自于父组件或者祖先组件的 state,这种情况下只要父组件或者祖先组件的 state 发生变化,子组件就会重新 render