背景
在用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>
)
}
我直接更新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>
)
}
可以看到count在内部更新,并没有引起ui的更新。
react官方解释
思考一下,为什么直接更新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是对内的。