文档
useState
-
useState如果是以函数作为参数,那要求是一个纯函数,不接受任何参数,同时需要一个任意类型的返回值作为初始值。
-
useState可以传入任何类型的参数作为初始值,当以一个函数作为参数进行传入的时候需要注意:
如果只传入了函数名,那么这个函数参数只会在初始化渲染的时候被调用,后续页面发生变化也不会触发函数;如果传入的是函数调用后的结果,那么当初始化渲染和后续页面变化的时候都会触发函数。import { useState } from 'react'; export default function Counter() { const [age, setAge] = useState(increment); // 因为传入的是函数名,所以只有在初始化的时候才触发,因此只有一个输出 const [age, setAge] = useState(increment()); // 传入的是函数返回的内容,所以当点击+1的按钮进行更新的时候也会触发increment函数,所以一直会有输出 function increment() { console.log('-----输出') return 0 } function add(){ setAge(a => a + 1); } return ( <> <h1>Your age: {age}</h1> <button onClick={() => { add(); }}>+1</button> </> ); }
箭头函数同理:
import { useState } from "react"; export default function Counter() { const [age, setAge] = useState(() => { console.log("-----输出"); return 0; }); const [age, setAge] = useState( (() => { console.log("-----输出"); return 0; })() ); function add() { setAge((a) => a + 1); } return ( <> <h1>Your age: {age}</h1> <button onClick={() => { add(); }} > +1 </button> </> ); }
-
setState是变更state的方法,它接受任何类型的值,包括函数。需要注意的是,set函数不会更新已经运行代码中的state状态变量,因此 ,当一个运行中的代码存在同时多次触发同一个set函数的时候,set中的state值其实都是之前没变化时的同一个。如果需要解决这个问题,可以向set函数传递一个更新函数,它必须是纯函数,只接受待定的 state 作为其唯一参数,并应返回下一个状态。此时,更新函数将会获取待定状态并从中计算下一个状态。
//假设 age 为 42,这个处理函数三次调用 setAge(age + 1): function add() { setAge(age + 1); // setAge(42 + 1),因为add函数已经运行了,set函数不会更新里面的age值,所以取得全是上一次的值,即42,因此,每个 setAge(age + 1) 调用变成了 setAge(43) setAge(age + 1); // setAge(42 + 1) setAge(age + 1); // setAge(42 + 1) }
解决这个问题,你可以向 setAge 传递一个更新函数,而不是下一个状态:
function handleClick() { setAge(a => a + 1); // setAge(42 => 43) setAge(a => a + 1); // setAge(43 => 44) setAge(a => a + 1); // setAge(44 => 45) }
这里,a => a + 1 是更新函数。它获取待定状态并从中计算下一个状态。
React 将更新函数放入队列中。然后,在下一次渲染期间,它将按照相同的顺序调用它们:
a => a + 1 将接收 42 作为待定状态,并返回 43 作为下一个状态。
a => a + 1 将接收 43 作为待定状态,并返回 44 作为下一个状态。
a => a + 1 将接收 44 作为待定状态,并返回 45 作为下一个状态。
现在没有其他排队的更新,因此 React 最终将存储 45 作为当前状态。按照惯例,通常将待定状态参数命名为状态变量名称的第一个字母,如 age 为 a。然而,你也可以把它命名为 prevAge 或者其他你觉得更清楚的名称。
其他参考:
React Hooks中常用Hooks的用法详解
React Hooks中常用Hooks钩子的用法详解