我不明白为什么我会陷入无限循环 useClick 我看到我使用 setVal 更改了 useEffect 内的状态值,但是useEffect应该仅对第二参数中指定的onClick起作用。我认为这是因为传给我的参数onClick被记录下来,但未调用回调(我使用 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>
}
答案 0 :(得分:5)
val
和setVal
将在每个渲染上更改,这又将导致incrementOnClick
成为新的函数引用,并且您的useClick
效果将始终被调用。
您可以改用setVal
作为第一个参数的功能。此函数获取当前的val
作为参数并返回新值。这样incrementOnClick
将始终具有相同的功能。
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>
上面的代码显示了如何摆脱无限循环并可能对实验有价值,但其中大部分不是必需的。您可以这样编写相同的功能:
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>
答案 1 :(得分:0)
看看您想做什么,我相信您缺少Hooks&React最有用的功能之一,那就是组成。
这是您所做的事的一个示例,但是对我来说,只需创建另一个名为<IncrementButton/>
的组件,就可以使代码更容易理解/调试。自定义钩子很棒,但是我相信这样做是错误的工具。
const { useEffect, useState } = React;
const IncrementButton = props => {
const {val, setVal, children} = props;
return <button
onClick={() => setVal(val + 1)}
>{children}</button>;
}
const Home = () => {
const [val, setVal] = useState(0);
return (
<div>
<div>{val}</div>
<IncrementButton val={val} setVal={setVal}>
Click me
</IncrementButton>
</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>