Обновление нескольких состояний в setTimeout

#javascript #reactjs #use-state

Вопрос:

 import { useEffect, useState } from "react";

export default function App() {
  const [criteria, setCriteria] = useState({});

  const handleCriteriaChange = (values) => {
    // setCriteria(prevCriteria => ({
    //   ...prevCriteria,
    //   ...values
    // }))
    setCriteria({
      ...criteria,
      ...values
    });
  };

  useEffect(() => {
    setTimeout(() => {
      handleCriteriaChange({
        courses: ["calculus", "psychology"]
      });
    }, 1000);

    setTimeout(() => {
      handleCriteriaChange({
        type: "manual"
      });
    }, 5000);

    setTimeout(() => {
      handleCriteriaChange({
        termLengths: [14, 7]
      });
    }, 10000);
    // eslint-disable-next-line
  }, []);

  console.log({ criteria: JSON.stringify(criteria) });
  return (
    <div className="App">
      <h1>Hello CodeSandbox {JSON.stringify(criteria)}</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
 

Я добавил логику для обновления объекта состояния с помощью разных ключей с интервалом в 5 секунд между каждым обновлением. И я ожидал, что все ключевые значения появятся в объекте состояния, но отображается только последнее обновление состояния. Почему я не могу получить все добавленные значения ключа:? Даже если есть пакетирование состояний, они обновляют состояние с помощью разных ключей.

Комментарии:

1. У вас есть устаревшая ссылка на ваше состояние handleCriteriaChange , заменяющая состояние старым состоянием.

2. Как это состояние может быть несвежим handleCriteriaChange ?

3. У useEffect вас есть только ссылка на первое handleCriteriaChange , которое было создано, внутри которой находится устаревшая ссылка на первое состояние.

Ответ №1:

проблема с вашей функцией состояния обновления handleCriteriaChange . переменная criteria пуста в useEffect функции и при ее использовании или назначении. вы должны использовать значение предыдущего состояния при обновлении состояния.

 import React from 'react';

import { useEffect, useState } from 'react';

export default function App() {
  const [criteria, setCriteria] = useState({});

  const handleCriteriaChange = (values) => {
   
    setCriteria(prev=> ({
      ...prev,
      ...values,
    }));
  };

  useEffect(() => {
    setTimeout(() => {
      handleCriteriaChange({
        courses: ['calculus', 'psychology'],
      });
    }, 1000);

    setTimeout(() => {
      handleCriteriaChange({
        type: 'manual',
      });
    }, 5000);

    setTimeout(() => {
      handleCriteriaChange({
        termLengths: [14, 7],
      });
    }, 10000);
    // eslint-disable-next-line
  }, []);

  console.log({ criteria: JSON.stringify(criteria) });
  return (
    <div className="App">
      <h1>Hello CodeSandbox {JSON.stringify(criteria)}</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
 

Комментарии:

1. Это сработало для меня. Отличный ответ….