Синхронно реагировать на состояние обновления

У меня есть компонент Master, который содержит несколько компонентов Child. Дочернее состояние сохраняется в Master. Первое состояние, которое получает ребенок, — FORM_LOADED. Затем у меня есть приведенный ниже код в моем главном компоненте.

const Master = (props) => {
  const [formStates, setFormStates] = useState()

  useEffect(() => {
    setFormStates({...formStates, Master: "FORM_LOADED"})
  },[])

  render (
    <>
      <Child view = "Model1" formStates = {formStates} setFormStates = {setFormStates} />
      <Child view = "Model2" formStates = {formStates} setFormStates = {setFormStates} />
      <pre>{JSON.stringify(formStates, undefined, 4)}</pre>
    </>
  )
}

const Child = (props) => {
  useEffect(() => {
    props.setFormStates({...props.formStates, [props.view]: "FORM_LOADED"})
  }, [])
  render (
    <p>{props.view}</p>
  )
}

Моя проблема в том, что переменная состояния formStates всегда получает:

{
  Master: "FORM_LOADED",
  Model2: "FORM_LOADED"
}

Model1 не появляется в formStates. Если я добавлю больше дочерних компонентов, в formStates будет отражен только последний компонент. Как я могу получить Model1 в formStates?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
0
81
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Я не уверен, что все понял, но в методе setState() вы можете получить старое значение. Вы можете сделать что-то вроде этого:

  useEffect(() => {
    props.setFormStates((oldVal) =>({...oldVal, ...props.formStates, [props.view]: "FORM_LOADED" }));
  });
  return <p>{props.view}</p>;
};```

Спасибо, это сработало. reactjs.org/docs/hooks-state.html не упоминает, что я могу использовать предыдущее состояние в хуке useState

Lakmal Premaratne 10.12.2020 13:49

Проблема может заключаться в том, что вы каждый раз перезаписываете свой старый объект новым. Пытаться:

const Child = (props) => {
  useEffect(() => {
    props.setFormStates(prevFormStates => ({...prevFormStates, [props.view]: "FORM_LOADED"}))
  }, [])
  render (
    <p>{props.view}</p>
  )
}

Спасибо, это сработало. reactjs.org/docs/hooks-state.html не упоминает, что я могу использовать предыдущее состояние в хуке useState

Lakmal Premaratne 10.12.2020 13:51

Привет, определенный вами подход никогда не будет работать, потому что вы устанавливаете состояние родителя в середине потока, где родитель находится в процессе, чтобы отобразить все свои дочерние элементы.

Я думаю, что вы пытаетесь проверить, все ли ваши дети отрендерились.

React ожидает монтирования всех дочерних компонентов перед вызовом componentDidMount для родителя.

Я думаю, это может помочь вам

Я использую функциональный компонент (извините, я не упомянул об этом в своем вопросе выше), и я решаю его после других ответов (использование предыдущего состояния)

Lakmal Premaratne 10.12.2020 13:51

Весь код из каждого хука useEffect выполняется до того же повторного рендеринга. Так работает Реакт. Так что каждый из них использует старое состояние formStates.

Вы можете использовать следующий код, чтобы использовать текущее состояние formState:

const Master = (props) => {
  const [formStates, setFormStates] = useState()

  useEffect(() => {
    setFormStates((prev) => ({...prev, Master: "FORM_LOADED"}))
  },[])

  render (
    <>
      <Child view = "Model1" formStates = {formStates} setFormStates = {setFormStates} />
      <Child view = "Model2" formStates = {formStates} setFormStates = {setFormStates} />
      <pre>{JSON.stringify(formStates, undefined, 4)}</pre>
    </>
  )
}

const Child = (props) => {
  useEffect(() => {
    props.setFormStates((prev) => ({...prev, [props.view]: "FORM_LOADED"}))
  }, [])
  render (
    <p>{props.view}</p>
  )
}

Спасибо, это сработало. reactjs.org/docs/hooks-state.html не упоминает, что я могу использовать предыдущее состояние в хуке useState

Lakmal Premaratne 10.12.2020 13:49

Другие вопросы по теме