闽公网安备 35020302035485号
了解一个框架的最好方式,便是从它的数据开始,无论是vue,亦或者react,都是如此。对于react来说,最重要的数据莫过于状态值state,在官方的新文档中,state被描述为一个组件的记忆,我们可以将其理解为显示在屏幕上的动态数据。
export default function Count(){
let num = 0
const handleClick = () => {
num += 1
}
return (
<>
<div>Count: { num }</div>
<button onClick={ handleClick }>+1</button>
</>
)
}
handleClick() 事件处理函数更新了局部变量 num。但存在两个原因使得屏幕上的num不会发生变化:const [state, setState] = useState(initialState);其中state变量用于保存渲染间的数据,而setState函数则用来更新变量并触发 React 再次渲染组件(即re-render),re-render会再次调用组件函数,并用新状态值替换旧的状态值去执行相应的渲染或操作,我们将 Count 组件用状态改写如下:
export default function Count(){
const [ num, setNum ] = useState(0)
// 堆代码 duidaima.com
const handleClick = () => {
setNum(num + 1)
}
return (
<>
<div>Count: { num }</div>
<button onClick={ handleClick }>+1</button>
</>
)
}
现在屏幕上的num就能实现动态变化了。
let [state, setState] = useState(initialState);或者这样:
const stateArr = useState(initialState);
react并没有严格限制这些写法,但是它们都是不规范的写法,这里就不得不谈及状态的不可变性了。在react的每一次组件渲染切片中,其内部的状态值在其渲染到屏幕上之前的那一刻,就已经固定下来了,后续无论什么样的操作,我们都不应该再对其造成影响,为什么要这么做呢?我们知道动画是由一帧帧快照组成的,react也是如此,在react中,每一次渲染就如同一帧快照切片,这样的每一帧快照,它的状态就必须自始至终保持不变,以便我们可以随时进行Time Travel,也不会出现前后渲染不一致的问题。
const [state, setState] = useState([
{ a: 0 },
{ b: 1 }
]);
// 堆代码 duidaima.com
// 不规范写法
const s = [...state]
s[0].a = -1
setState(s)
// 规范写法
const s = [...state]
s[0] = { ...s[0], a: -1 }
setState(s)
维持状态不可变性的最好方法便是拷贝,如何以最低的成本去进行拷贝,需要我们自己去衡量把握。