setState时请使用箭头函数
示例
function Test (props) {
/*setState时候请使用箭头函数*/
const [noArr,setNoArr]=useState(0)
const [arr,setArr]=useState(0)
return(
<>
<Button onClick={()=>{setNoArr(noArr+1);setNoArr(noArr+1)}}>
不用箭头函数设置值:{noArr}
</Button>
<Button onClick={()=>{setArr(arr=>arr+1);setArr(arr=>arr+1)}}>
使用箭头函数设置值:{arr}
</Button>
</>
)
}
结果
- 点击一次之后发现虽然都是setState两次,但是只有使用箭头函数才能保证每次set的时候获取的都是最新的值。
- 对于
setNoArr(noArr+1)
,虽然写了两次,但是对于他们来说,拿到的noArr都是0,
每次setState时,都要是全新的值
示例
/*每次setState时,都要是全新的值*/
const [notNew,setNotNew]=useState(0)
const [notNewArr,setNotNewArr]=useState([])
const [notNewObj,setNotNewObj]=useState({})
useEffect(()=>{
console.log('useEffect notNew',notNew);
console.log('useEffect notNewArr',notNewArr);
console.log('useEffect notNewObj',notNewObj);
},[notNew,notNewArr,notNewObj])
return (
<Button onClick={()=>{
setNotNew(0)
setNotNewArr(notNewArr=>{
notNewArr.push(1)
return notNewArr
})
setNotNewObj((notNewObj)=>{
notNewObj.name='aaa'
return notNewObj
})
}}>
设置不是全新的值
</Button>
<Button onClick={()=>{
setNotNew(Number(0))
setNotNewArr(notNewArr=>[...notNewArr,1])
setNotNewObj((notNewObj)=>{return {...notNewObj,name:'aaa'}})
}}>
设置是全新的值
</Button>
<Button onClick={()=>{
console.log('notNew',notNew);
console.log('notNewArr',notNewArr);
console.log('notNewObj',notNewObj);
}}>
打印值
</Button>
)
结果
- 不是新值的时候,组件没有重新渲染,但是值的确的变化了。
- 每次都是新值的时候发现组件监听到变化重新渲染了
解释
值相同的话是setState的时候是不会执行的。数组和对象不是变化了吗?为什么也不识别呢?引用形变量useState监听的时候是潜监听,不会监听你里面到底变没变,我只监听你的引用变没变,obj.name=1 ,你obj里面变了,但是你obj的引用没有变所以useState认为没变化。所以有的人setState之后说为什么我界面上列表渲染没有变化就是因为这个
state之间有依赖的话请使用useReducer
示例
/*state之间有依赖的话请使用useReducer*/
const [a,seta]=useState(0)
const [b,setb]=useState(0)
const [total,setTotal]=useState(0)
return (
<Button onClick={()=>{
seta(a=>a+1)
setb(b=>b+1)
setTotal(a+b)
}}>
获取a和b的合-Total:{total}
</Button>
<p>a:{a}</p>
<p>b:{b}</p>
)
结果
- 发现total并不是2,而是0+0=0
解释
和第一点类似,它获取不到最新的值,计算时候拿的是第一次的值,而不是seta和setb之后的新值。这里也没有箭头函数来帮你。
使用useReducer
const initVal={
a:0,
b:0,
total:0
}
function reducer(state,action) {
if (action.type === 'total') {
return {
...state,
a:state.a+1,
b:state.b+1,
total:state.a+1+state.b+1
}
}
}
function Test (props) {
/*state之间有依赖的话请使用useReducer*/
const [a,seta]=useState(0)
const [b,setb]=useState(0)
const [total,setTotal]=useState(0)
//使用useReducer
const [state,dispatch]=useReducer(reducer,initVal)
return(
<>
<p>state之间有依赖的话请使用useReducer</p>
<Button onClick={()=>{
seta(a=>a+1)
setb(b=>b+1)
setTotal(a+b)
}}>
获取a和b的合-Total:{total}
</Button>
<p>a:{a}</p>
<p>b:{b}</p>
<Button onClick={()=>{
dispatch({type:'total'})
}}>
使用useReducer获取的-Total:{state.total}
</Button>
<p>a:{state.a}</p>
<p>a:{state.b}</p>
</>
)
}