反应状态没有在 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.setItemsetResults 更新状态之前执行。你可以做一些重构来让它工作:

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]);