ReactJS: изменение состояния дочернего компонента - PullRequest
1 голос
/ 21 февраля 2020

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

function Parent(props) {
const [parentState, setParentState] = useState(someState);

return (
  <button onClick={() => setParentState(newState)>Button</button>
  <ChildComponent parentState={parentState} />
}

function Child(props) {
const [childState, setChildState] = useState(getState(props.parentState));
}

Нажатие на кнопку в этом примере должно изменить нетривиальное изменение триггера состояния в дочернем компоненте (который использует parentState в качестве параметра для создания своего собственного состояния).

Я думаю, что первым ответом на проблему было бы поднять состояние - однако я бы не хотел этого делать, потому что есть много дочерних объектов, генерируемых через Функция .map - мне нужно сохранить их состояния в массиве и распространить его на все дочерние компоненты. Значение в родительском компоненте является глобальным значением, относящимся ко всем дочерним элементам, и все дочерние элементы должны изменять свои состояния при изменении parentState.

Есть ли какой-нибудь хороший способ добиться этого без отмены состояний дочерних компонентов? Надеюсь, я достаточно хорошо описал проблему - если нет, я буду рад обновить информацию.

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

Исходя из вашего уточняющего комментария, вот несколько идей о том, как поступить. В зависимости от того, что содержит объект parentState, могут быть более эффективные способы сделать это, но, надеюсь, это поможет стимулировать некоторые идеи.

  1. Используйте parentState двумя способами.
    1. В качестве Child проп. Это всегда будет обновляться всякий раз, когда Parent меняет свое значение.
    2. В качестве начального значения одного из Child хуков useState. Это инициализирует производное состояние дочернего элемента, но позволит состоянию Child отклоняться со временем в зависимости от действий пользователя в компоненте Child.
  2. Используйте useEffect крючки для активации функции Child getData при изменении переменной parentState или при изменении переменной childStateSettings.
  3. Используйте несколько useState хуков в Child, чтобы отделить непроизводную часть состояния от унаследованной / производной части состояния Child. Для производного состояния, childStateSettings, используйте parentState в качестве начального значения.

Таким образом, Child становится примерно таким:

import { useEffect, useState } from 'react';

function Child(props) {
  const { parentState } = props;

  // initial value of child settings from parent
  const [childStateSettings, setChildStateSettings] = useState(parentState); 

  // non-inherited/non-derivative state of child
  const [childStateData, setChildStateData] = useState({}); 

  // Depending on the number of settings and ways in which
  //  the user can make them different than the parent/global settings,
  //  you may want to have even more useState hooks to further separate
  //  the settings into individual pieces. I think this would simplify
  //  your various `onChange`/`onSelection'/etc. function logic, but I
  //  couldn't say for certain without more details.


  useEffect(() => {
    getData(childStateDerivative, childStateNonDerivative);
  }, [parentState, childStateSettings]};

  // pseudocode invented by me as a guess of 
  //  how you might need to use things based on your comment
  const getData = (parentState, childState) => {
    // last spread object takes precedence if duplicate keys are present in both objects
    const combinedState = { ...parentState, ...childState }; 
    API.get('http://some_path', combinedState).then(data => {
      setChildStateData(data);
    });
  };

  // you'll probably draw some inputs so that the 
  //  user can alter the child's state settings but
  //  I didn't bother trying to guess what that might look like.
  return (<>...</>); 

}
1 голос
/ 21 февраля 2020

Ребенок не должен иметь своего собственного состояния. Это должно полностью зависеть от родительского состояния / реквизита.

function Parent(props) {
const [parentState, setParentState] = useState(someState);

return (
  <button onClick={() => setParentState(newState)>Button</button>
  <ChildComponent parentState={parentState} />
}

function Child(props) {
}
0 голосов
/ 21 февраля 2020

Когда вы меняете родительское состояние, ребенок перерисовывается. Вы можете использовать setState () в конструкторе, чтобы изменить ваше дочернее состояние, когда оно воссоздается в DOM.

...