useState无论调用多少次,相互之间是独立的。react是根据useState出现的顺序来保证多个useState之间是相互独立 ```javascript let showFruit = true; function ExampleWithManyStates() { const [age, setAge] = useState(42);
if(showFruit) { const [fruit, setFruit] = useState(‘banana’); showFruit = false; } const [todos, setTodos] = useState([{ text: ‘Learn Hooks’ }]); }
//第一次渲染 useState(42); //将age初始化为42 useState(‘banana’); //将fruit初始化为banana useState([{ text: ‘Learn Hooks’ }]); //将todos初始化为[{ text: ‘Learn Hooks’ }]
//第二次渲染
useState(42);  //读取状态变量age的值(这时候传的参数42直接被忽略)
// useState(‘banana’);
useState([{ text: ‘Learn Hooks’ }]); //读取到的却是状态变量fruit的值,导致报错
- 解决useState多次渲染的问题```javascript// 以下代码执行完会导致页面渲染两遍const [loading, setLoading] = useState(true);const [data, setData] = useState(null);useEffect(async () => {const res = await axios.get("xxx");setLoading(false);setData(res);}, []);// 原因是,在React中,同步代码会合并渲染,异步代码不会合并渲染。// 以下代码只会渲染一次,它会将setLoading和setData进行合并。这个其实和类组件是一样的,在异步函数中不会合并setState。const [loading, setLoading] = useState(true);const [data, setData] = useState(null);useEffect(() => {setLoading(false);setData({ a: 1 });}, []);// 解决方案一:多个状态合并到一个状态中const [request, setRequest] = useState({ loading: true, data: null });useEffect(async () => {const res = await axios.get("xxx");setRequest({ loading: false, data: res });}, []);// 缺点:如果只想setState一个依赖项时,需要将别的依赖项也要传进去,否则这个值会丢失。React内部并不会帮你做去合并setRequest({ data: res }); // 就会导致loading值丢失了。// 解决方案是使用setRequest({ ...request, data: res }) 或者 setRequest((prevState) => ({ ...prevState, data: res }));// 解决方案二:写一个自定义合并依赖项的hookconst useMergeState = (initialState) => {const [state, setState] = useState(initialState);const setMergeState = (newState) =>setState((prevState) => ({ ...prevState, newState }));return [state, setMergeState];};const [request, setRequest] = useMegeState({ loading: false, data: null });useEffect(async () => {const res = await axios.get("xxx");setRequest({ loading: true, data: res });// setRequest({ data: { a: 1 } }); // loading 状态不会丢失,还是 true}, []);// 解决方案三:使用useReducerconst initState = { loading: false, data: null }function loginReducer(state, action) {if(action.type==='login'){return {...state,...action.newState}}}const [state, dispatch] = useReducer(loginReducer,initState);useEffect(async () => {const res = await axios.get("xxx");dispatch({ type: 'login', newState: {loading: true, data: res} });// setRequest({ data: { a: 1 } }); // loading 状态不会丢失,还是 true}, []);
