4 回答

TA貢獻1900條經驗 獲得超5個贊
我相信如果沒有一些解決方法,這幾乎是不可能實現的。要調用setState或不調用,我們必須訪問當前狀態值。如果我們傳入state依賴數組,這是可能的。但隨后,該間隔將每秒重新創建。
也可以使用 refs 來實現,但是目前還沒有正確的方法來監聽ref 的更改。
更新:看起來它可以很好地用作useRef以前的數據持有者。感謝安豪2。
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>

TA貢獻1772條經驗 獲得超8個贊
您可能需要采取一些不同的方法。你不需要隨機值,你想要它是否能被 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;
}

TA貢獻1982條經驗 獲得超2個贊
我們最好更改狀態來存儲 is5x 而不是值。一種可能的解決方案是使用 useRef 來檢查我們是否應該每秒更新該值。然后,同步 useRef 和狀態值。
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;
};
添加回答
舉報