反应状态没有在 useEffect() 上给出正确的值
React state not giving correct value on useEffect()
我正在尝试使用 React 构建分解算法。 我想根据分解 的结果将 results
添加到 LocalStorage
。但是,LocalStorage
设置以前的结果而不是当前的结果。
我认为这是因为 useEffect
运行 在每个新的 [number]
(=用户输入)而不是基于 [results]
。但是,在新用户输入提交时我需要 useEffect
到 运行,因为那是必须触发分解的时候。
在因式分解完成后(如果可能,在 finally
块上),我如何让 localStorage
设置正确的结果?
const [results, setResults] = useState({
default: [],
detailed: [],
isPrime: '',
});
const { number } = props
useEffect(() => {
handleWorker(number);
//accessing results here will give previous results
}, [number]);
const handleWorker = number => {
try {
const worker = new Worker(new URL('facto.js', import.meta.url));
worker.postMessage({ number, algorithm });
worker.onmessage = ({ data: { facto } }) => {
setResults({ ...facto });
//the worker 'streams live' results and updates them on setResults
};
} catch(error) {
console.log(error.message)
} finally {
localStorage.setItem(number, results)
//here, results is not current state but previous one
}
};
请注意,其他一切正常
谢谢
这是您需要的(可能):
const [results, setResults] = useState({ /* YOUR STATE */ });
const { number } = props
const handleWorker = useCallback((number) => {
// DO WHATEVER YOU NEED TO DO HERE
},[]); // IF YOU DEPEND ON ANY MUTABLE VARIABLES, ADD THEM TO THE DEPENDENCY ARRAY
useEffect(() => {
// DO WHATEVER YOU NEED TO DO HERE
// INSTEAD OF localStorage.setItem(number, results)
// DO localStorage.setItem(number, { ...facto })
}, [number,handleWorker]);
如果有效请告诉我。
我认为您可以将结果状态作为 useEffect 的依赖项传递,因此只要结果值发生变化,useEffect 就会运行
useEffect(() => { //code goes here}, [results]);
假设结果也取决于函数 handleWorker
useEffect(() => { //code goes here},
[results,handleWorker]);
您正在获取之前的值,因为 localStorage.setItem
在 setResults
更新状态之前执行。你可以做一些重构来让它工作:
const [results, setResults] = useState({
default: [],
detailed: [],
isPrime: '',
});
const { number } = props;
const workerRef = useRef(new Worker(new URL('facto.js', import.meta.url)));
const worker = workerRef.current;
useEffect(()=> {
//-> create the listener just once
worker.onmessage = ({ data: { facto } }) => {
setResults({ ...facto });
};
}, []);
useEffect(() => {
//-> send message if number changed
worker.postMessage({ number, algorithm });
}, [number]);
useEffect(() => {
//-> update localStorage if results changed
localStorage.setItem(number, results)
}, [results]);
我正在尝试使用 React 构建分解算法。 我想根据分解 的结果将 results
添加到 LocalStorage
。但是,LocalStorage
设置以前的结果而不是当前的结果。
我认为这是因为 useEffect
运行 在每个新的 [number]
(=用户输入)而不是基于 [results]
。但是,在新用户输入提交时我需要 useEffect
到 运行,因为那是必须触发分解的时候。
在因式分解完成后(如果可能,在 finally
块上),我如何让 localStorage
设置正确的结果?
const [results, setResults] = useState({
default: [],
detailed: [],
isPrime: '',
});
const { number } = props
useEffect(() => {
handleWorker(number);
//accessing results here will give previous results
}, [number]);
const handleWorker = number => {
try {
const worker = new Worker(new URL('facto.js', import.meta.url));
worker.postMessage({ number, algorithm });
worker.onmessage = ({ data: { facto } }) => {
setResults({ ...facto });
//the worker 'streams live' results and updates them on setResults
};
} catch(error) {
console.log(error.message)
} finally {
localStorage.setItem(number, results)
//here, results is not current state but previous one
}
};
请注意,其他一切正常
谢谢
这是您需要的(可能):
const [results, setResults] = useState({ /* YOUR STATE */ });
const { number } = props
const handleWorker = useCallback((number) => {
// DO WHATEVER YOU NEED TO DO HERE
},[]); // IF YOU DEPEND ON ANY MUTABLE VARIABLES, ADD THEM TO THE DEPENDENCY ARRAY
useEffect(() => {
// DO WHATEVER YOU NEED TO DO HERE
// INSTEAD OF localStorage.setItem(number, results)
// DO localStorage.setItem(number, { ...facto })
}, [number,handleWorker]);
如果有效请告诉我。
我认为您可以将结果状态作为 useEffect 的依赖项传递,因此只要结果值发生变化,useEffect 就会运行
useEffect(() => { //code goes here}, [results]);
假设结果也取决于函数 handleWorker
useEffect(() => { //code goes here},
[results,handleWorker]);
您正在获取之前的值,因为 localStorage.setItem
在 setResults
更新状态之前执行。你可以做一些重构来让它工作:
const [results, setResults] = useState({
default: [],
detailed: [],
isPrime: '',
});
const { number } = props;
const workerRef = useRef(new Worker(new URL('facto.js', import.meta.url)));
const worker = workerRef.current;
useEffect(()=> {
//-> create the listener just once
worker.onmessage = ({ data: { facto } }) => {
setResults({ ...facto });
};
}, []);
useEffect(() => {
//-> send message if number changed
worker.postMessage({ number, algorithm });
}, [number]);
useEffect(() => {
//-> update localStorage if results changed
localStorage.setItem(number, results)
}, [results]);