想象一下,这个钩子每秒更改一次值,如果随机值是5的倍数,则返回true,否则为false。我该怎么做才能停止每秒重新渲染?
PS:我尝试过使用Memo和useRef返回始终相同的对象,但它仍在重新渲染。
请帮助
const useRandomIs5x = () => {
const [state, setState] = useState(0);
useEffect(() => {
const t0 = setInterval(() => {
setState(getRandomValue())
}, 1000)
return () => clearInterval(to)
}, [])
return state % 5 === 0;
}
const Root = () => {
const bool = useRandomIs5x();
console.log("I'm re-rendering every second", bool)
return <div>test</div>
}
我相信如果没有一些解决方案,这几乎是不可行的。要调用或不调用setState
,我们必须访问当前状态值。如果我们在依赖数组中传递state
,这是可能的。但是,每一秒都会重新创建间隔。
对于refs,这也是可行的,但(目前(还没有正确的方法来听取ref的更改。
更新:使用useRef
作为上一个数据持有者似乎可以很好地工作。多亏了anhau2。
const { useEffect, useState, useRef } = React;
const useRandomIs5x = () => {
const [state, setState] = useState(true);
const ref = useRef(null);
useEffect(() => {
const t0 = setInterval(() => {
const value = Math.floor(Math.random() * 5) % 5 === 0;
if (value === ref.current) return;
ref.current = value;
setState(value);
}, 1000);
return () => clearInterval(t0);
}, []);
return state;
}
const Root = () => {
const bool = useRandomIs5x();
console.log('re-render!', bool);
return <div>test</div>
}
ReactDOM.render(<Root />, 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>
第页。S.期待着任何其他的想法如何处理它。
您可能需要以不同的方式来处理它。你不想要随机值,你想要它是否能被5整除。所以这就是应该处于状态并从钩子中返回的内容。随机值可以只是一个参考值。所以尝试这样的东西(代码没有测试,但应该给你大致的想法(:
const useRandomIs5x = () => {
const [divisibleBy5, setDivisibleBy5] = useState(true);
const randomValue = useRef(0);
useEffect(() => {
const t0 = setInterval(() => {
// Set the new random value into a ref so as to not cause re-render
randomValue.current = getRandomValue();
const randIsDivisibleBy5 = randomValue.current % 5 === 0;
// Only if it changes do we update the boolean state and trigger re-render
if (randIsDivisibleBy5 !== divisibleBy5) {
setDivisibleBy5(randIsDivisibleBy5);
}
}, 1000);
return () => clearInterval(to);
}, []);
// Return the boolean state value instead
return divisibleBy5;
}
我们最好将状态更改为存储is5x,而不是值。一种可能的解决方案是使用useRef检查是否应该每秒更新一次值。然后,同步useRef和state值。
const useRandomIs5x = () => {
const [state, setState] = useState(false);
const prevIs5x = useRef(false);
useEffect(() => {
const t0 = setInterval(() => {
const is5x = getRandomValue() % 5 === 0;
const isDiff = is5x !== prevIs5x.current;
prevIs5x.current = is5x;
if (isDiff) {
setState((prevState) => !prevState);
}
}, 1000);
return () => clearInterval(t0);
}, []);
return state;
};
我可以在回调中使用这个库的react钩子来解决这个问题将挂钩与部件隔离。
检查这个沙箱示例