react系列-props&state

55 阅读1分钟

背景

在用react开发的时候,我们经常会使用组件复用,因此父组件会给子组件传参数(props),还有就是子组件内部也有自己的状态管理(state),有啥区别呢。

props

function Child(props) {
    return (
        <div>{props.userName}</div>
    )
}
function Parent() {
    const info = {
        userName: '张三'
    }
    return (
        <div>
            <Child {...info} />
        </div>
    )
}

react单向数据流的特性,props不能被组件内部修改。父组件的props会被多个子组件引用,如果子组件能改变props会引起组件更新,违背了UI=Component(props)的设计初衷。
react官方:

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改

react源码中

const ReactElement = function(type, key, ref, self, source, owner, props) {
// ......
    if (Object.freeze) {
      Object.freeze(element.props); // 使props不可改变
      Object.freeze(element);
    }
// ......
}

state

组件内部的数据状态自己管理,可以自由的修改,多个state为了提高性能会被合并。
列如:内部自己管理数据

function Counter() {
    const [count, setCount] = useState(1);
    useEffect(() => {
        setCount(count => count+1);
    }, []);
    return (
        <div>{count}</div>
    )
}

image.png

我直接更新state不通过setState

function Counter() {
    let [count, setCount] = useState(1);
    useEffect(() => {
        setInterval(() => {
            count++;
            console.log('count =>', count);
        }, 1000)
        setCount(count => count+1);
    }, []);
    return (
        <div>{count}</div>
    )
}

image.png 可以看到count在内部更新,并没有引起ui的更新。
react官方解释

image.png 思考一下,为什么直接更新count不能引起ui更新?
我的理解是,如果直接更新conut能引起ui的变化,这就是同步更新了,将会对性能产生很大的影响。因而使用setState
源码如下:

function useState(initialState) {
  var dispatcher = resolveDispatcher();
  return dispatcher.useState(initialState);
}
function updateReducer(reducer, initialArg, init){
      // ...
      var dispatch = queue.dispatch;
      return [hook.memoizedState, dispatch];
}

其实setState最后返回的是一个dispatch,用于更新state,最后实现ui的更新。

总结

props是对外的,state是对内的。