state 与 setState、单向数据流

state 与 props 的选择

/**
 * 1. 如果想使用组件的时候,传入数据 - props组件配置
 * 2. 如果是组件内部使用的数据 - state 私有数据(状态)
 */

state 的使用注意事项

  1. 必须使用 setState 方法来更改 state
  2. 多个 setState 是会合并调用
  3. props 和 state 更新数据要谨慎,尽量避免直接依赖他们
    1. 因为很可能是在异步程序中更新
  4. setState 操作合并的原理 - 浅合并
/**
 *      ❌ this.setState({
 *            result: this.state.result + this.props.content
 *         })
 *      ✅ this.setState((state, props) => {
 *            // state: 上一个 state
 *            // props: 此次更新时被使用的 props
 *            result: state.result + props.content
 *         })
 * 
 *      setState 操作合并的原理 - 浅合并
 *      ✅ this.setState({
 *            arr: [...this.state.arr, 4]
 *         })
 */
/**
 * 组件无论如何都是不知道其他组件是否是有状态的
 * 组件也并不关心其他组件是函数组件还是类组件
 * 
 * state 是组件内部特有的数据封装
 * 其他组件是无法读写修改该组件的 state 的
 * 组件可以通过其他组件调用的时候传入属性来传递 state 的值
 * props 虽然是响应式的,但在组件内部是只读的,所以你仍然是无法修改其他组件的 state
 */
class DateTime extends React.Component {
  constructor(props) {
    super(props);
  }
  state = {
    dateTime: new Date().toString()
  }

  // 组件已经被挂载到了真实DOM中后,运行的函数
  componentDidMount() {
    this.t = setInterval(() => {
      this.setState({
        dateTime: new Date().toString()
      });
    }, 1000);
  }
  // 组件卸载之前执行
  componentWillUnmount() {
    clearInterval(this.t);
    this.t = null;
    console.log('Over');
  }
  render() {
    return (
      <h2 id="dateTime">{ this.state.dateTime }</h2>
    )
  }
}

class Board extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <DateTime />
    )
  }
}

ReactDOM.render(
  <Board />,
  document.getElementById('app')
)

// 卸载组件
setTimeout(() => {
  ReactDOM.unmountComponentAtNode(document.getElementById('app'))
}, 5000);

单向数据流

数据(状态)从父到子,由上而下传递的这种方式叫做单向数据流

总结

对象式的setState

setState(stateChange, [callback])

函数式的setState

setState(updater, [callback])