无限循环 React 钩子 [英] Infinite loop React hooks
问题描述
我不明白为什么我会陷入无限循环useClick 我看到我使用 setVal 更改了 useEffect 内的状态值,但 useEffect 应该只对第二个参数中指定的 onClick 起作用.我认为这是因为我传递的参数 onClick 已被记忆但未调用回调(我使用 console.log('go set')
检查了这一点function useClick(onClick, setVal, val) {React.useEffect(() => {console.log('点击');setVal(val + 1);}, [onClick]);}const Home = () =>{const [val, setVal] = React.useState(0);const incrementOnClick = React.useCallback(() => {console.log('去设置');setVal(val + 1);} , [setVal, val]);useClick(incrementOnClick, setVal, val);返回 <div>{val}</div><button onClick={incrementOnClick}>点击我</button>}
val
和 setVal
将在每次渲染时发生变化,进而导致 incrementOnClick
成为一个新的函数引用,你的 useClick
效果会一直被调用.
您可以改为提供一个函数作为 setVal
的第一个参数.此函数获取当前 val
作为参数并返回新值.这样 incrementOnClick
将始终是相同的功能.
const { useEffect, useState, useCallback } = React;函数 useClick(onClick, setVal, val) {useEffect(() => {console.log("点击");setVal(val + 1);}, [onClick]);}const Home = () =>{const [val, setVal] = useState(0);const incrementOnClick = useCallback(() => {console.log("去设置");setVal(val => val + 1);}, []);useClick(incrementOnClick, setVal, val);返回 (<div><div>{val}</div><button onClick={incrementOnClick}>点击我</button>
);};ReactDOM.render(
<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>
上面的代码展示了如何摆脱无限循环并且对实验很有价值,但大部分都不是必需的.您可以改为编写相同的功能:
const { useState } = React;const Home = () =>{const [val, setVal] = useState(1);返回 (<div><div>{val}</div><button onClick={() =>setVal(val + 1)}>点击我</button>
);};ReactDOM.render(
<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>
I don't understand why I'm getting infinite loop in useClick I see that I change state value inside useEffect using setVal but useEffect should work only on onClick as specified in second param. I thought that it is because the param onClick i pass is memoized but the callback is not called(i checked that using console.log('go set')
function useClick(onClick, setVal, val) {
React.useEffect(() => {
console.log('Click');
setVal(val + 1);
}, [onClick]);
}
const Home = () => {
const [val, setVal] = React.useState(0);
const incrementOnClick = React.useCallback(() => {
console.log('go set');
setVal(val + 1);
} , [setVal, val]);
useClick(incrementOnClick, setVal, val);
return <div>
<div>{val}</div>
<button onClick={incrementOnClick}>Click me</button>
</div>
}
val
and setVal
will change on every render, which in turn will cause incrementOnClick
to become a new function reference, and your useClick
effect will always be invoked.
You could instead give a function as first argument to setVal
. This function gets the current val
as argument and returns the new value. This way incrementOnClick
will always be the same function.
const { useEffect, useState, useCallback } = React;
function useClick(onClick, setVal, val) {
useEffect(() => {
console.log("Click");
setVal(val + 1);
}, [onClick]);
}
const Home = () => {
const [val, setVal] = useState(0);
const incrementOnClick = useCallback(() => {
console.log("go set");
setVal(val => val + 1);
}, []);
useClick(incrementOnClick, setVal, val);
return (
<div>
<div>{val}</div>
<button onClick={incrementOnClick}>Click me</button>
</div>
);
};
ReactDOM.render(<Home />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
The code above shows how you could get away from the infinite loop and could be valuable for experimentation, but most of it isn't necessary. You could write the same functionality like this instead:
const { useState } = React;
const Home = () => {
const [val, setVal] = useState(1);
return (
<div>
<div>{val}</div>
<button onClick={() => setVal(val + 1)}>Click me</button>
</div>
);
};
ReactDOM.render(<Home />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
这篇关于无限循环 React 钩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!