当前位置: 首页 > Web前端 > HTML

使用useState多次渲染

时间:2023-03-27 22:53:52 HTML

使用useState多次渲染在使用hooks的时候,经常会写如下代码,然后发现页面渲染了两次,有时候会比较头疼。const[loading,setLoading]=useState(true);const[数据,setData]=useState(null);useEffect(async()=>{constres=awaitaxios.get("xxx");setLoading(false);setData(res);},[]);在React中,同步代码会被合并渲染,异步代码不会被合并渲染。下面的代码只会渲染一次,它会结合setLoading和setData。这其实和类组件是一样的,异步函数中不会合并setState。const[loading,setLoading]=useState(true);const[数据,setData]=useState(null);useEffect(()=>{setLoading(false);setData({a:1});},[]);在class组件中解决多次渲染的问题比较容易,但是在hooks中比较麻烦。方法一:将多个状态合并为一个状态将所有依赖状态合并到一个对象中,在setState中一起设置,解决多次渲染的问题,如下代码const[request,setRequest]=useState({loading:true,data:null});useEffect(async()=>{constres=awaitaxios.get("xxx");setRequest({loading:false,data:res});},[]);但这有一个问题。如果只想setState一个依赖,需要传入其他依赖,否则这个值会丢失。React不会在内部为您进行合并。setRequest({数据:资源});//缺少加载值。解决方案是使用扩展运算符setRequest({...request,data:res});//或setRequest((prevState)=>({...prevState,data:res}));方法二:写一个每次自定义合并依赖的hook都是setState的时候用扩展操作符合并依赖太麻烦了。使用React自定义钩子函数编写一个合并依赖项的useMergeState钩子。自定义钩子需要从使用开始。constuseMergeState=(initialState)=>{const[state,setState]=useState(initialState);constsetMergeState=(newState)=>setState((prevState)=>({...prevState,newState}));return[state,setMergeState];};/*使用*/const[request,setRequest]=useMegeState({loading:false,data:null});useEffect(async()=>{constres=awaitaxios.get("xxx");setRequest({loading:true,data:res});//...setRequest({data:{a:1}});//加载状态不会丢失,否则为true},[]);方案三:使用useReducerReact提供了useReducer来管理依赖,而不是使用useState。const[request,setRequest]=useReducer((prevState,newState)=>({...prevState,newState}),{loading:false,data:null});useEffect(async()=>{constres=awaitaxios.get("xxx");setRequest({loading:true,data:res});//...setRequest({data:{a:1}});//加载状态不会丢失,依然为true},[]);如果想获取之前的状态,需要修改上面的代码。const[request,setRequest]=useReducer((prevState,newState)=>{constnewWithPrevState=typeofnewState==="function"?newState(prevState):newState;return{...prevState,newWithPrevState})},{加载:false,data:null});useEffect(async()=>{constres=awaitaxios.get("xxx");setRequest((prevState)=>{return{loading:true,data:res}});//...setRequest({data:{a:1}});//加载状态不会丢失,否则为true},[]);参考文章:https://stackoverflow.com/que...