Joj*_*oji 4 javascript reactjs
这是现场演示:https://codesandbox.io/s/strange-bash-qj7ld ?file=/src/App.js
所以我有一个这样的组件
const fn = () => {
console.log("useState");
return ["string"];
};
export default function App() {
const [counter, setCounter] = useState(0);
const [nonprimitive, setNonprimitive] = useState(fn());
useEffect(() => {
console.log("useEffect");
}, [nonprimitive]);
return (
<>
<button onClick={() => setCounter(counter + 1)}>Counter {counter}</button>
<div>{nonprimitive[0]}</div>
</>
);
}
Run Code Online (Sandbox Code Playgroud)
每次我单击该按钮时,计数器都会增加并且组件将重新渲染。然后fn()会再次调用,然后会返回一个数组。并在发生变化useEffect时触发nonprimitive。我有两个问题:
useEffect只触发一次,而不是每次后续调用都触发?nonprimitive是一个数组,它是非原始类型,因此即使其中的字符串项保持不变,它每次也应该不同。React 似乎正在幕后进行一些深入的比较。useState每当组件重新渲染时,gets 都会打印两次?当我按下按钮时,即 console.log("useState");内部被调用两次。fn为什么
useEffect只触发一次,而不是每次后续调用都触发?nonprimitive是一个数组,它是非原始类型,因此即使其中的字符串项保持不变,它每次也应该不同。React 似乎正在幕后进行一些深入的比较。
重点useState是在组件的渲染中保留值。组件第一次渲染时useState(fn())被调用并nonprimitive获取 value ["string"]。在后续渲染中,useState(fn())再次调用(因为毕竟它仍然是标准函数调用,因此日志记录再次发生),但 React 知道这不是您的第一次渲染,因此它会丢弃参数(fn) 并返回先前存储的值,该值在引用上是相同的。
如果你不希望 React 在每次渲染时调用你的初始状态创建(例如,如果你的初始状态非常复杂或计算起来非常耗时),你可以向它传递一个函数,它只会在初始渲染时调用。
const [nonprimitive, setNonprimitive] = useState(() => fn());
Run Code Online (Sandbox Code Playgroud)
在您的情况下,由于初始状态已经包装在函数中,因此您可以等效地编写
const [nonprimitive, setNonprimitive] = useState(fn);
Run Code Online (Sandbox Code Playgroud)
为什么
useState每当组件重新渲染时,gets 都会打印两次?当我按下按钮时,即console.log("useState");内部被调用两次。fn
如果您查看 index.js,您会发现您的App组件被包装在<React.StrictMode>. React 严格模式将有意多次运行某些渲染,以帮助您捕获代码中的副作用和钩子违规。