Как создать контролируемый ввод с нуля в React - PullRequest
1 голос
/ 01 мая 2020

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

Я сделал значение, а реквизиты onChange необязательными, так как я также хочу поддержать случай, когда вы используете Child как неконтролируемый вход.

Работают как неконтролируемые, так и необработанные контролируемые варианты Child. Однако обработанный управляемый вариант не дает.

Есть идеи, как заставить это работать? Я связал свой JSFiddle ниже с моим минимальным примером, показывающим мою проблему:

https://jsfiddle.net/numberjak/wufdh0ys/3/

Код:

const Parent = () => {
    const [parentValue, setParentValue] = React.useState(0);

  return (
    <div>
      Should act like uncontrolled input (i.e. value should change) [WORKS]
      <Child />
      Should act like controlled input (i.e. value should change because onChange handler passed in) [DOESN'T WORK]
      <Child value={parentValue} onChange={setParentValue} />
      Should act like controlled input, except no onChange handler means value shouldn't change [WORKS]
      <Child value={5} />
    </div>
  );
};

const Child = ({value, onChange}) => {
    const [childValue, setChildValue] = React.useState(value !== undefined ? value : 0);

  const handleOnChange = (newValue) => {
    if (value === undefined) {
        setChildValue(newValue);
    }

    if (onChange !== undefined) {
        onChange(newValue);
    }
  };

  return (
    <GrandChild value={childValue} onChange={handleOnChange} />
  );
};

const GrandChild = ({value, onChange}) => {
    const handleOnClick = () => {
    onChange(value + 1);
  };

  return (
    <div className="grand-child" onClick={handleOnClick}>{value}</div>
  );
};

ReactDOM.render(<Parent />, document.querySelector("#app"))

1 Ответ

2 голосов
/ 01 мая 2020

Это происходит потому, что пропеллер value, который вы передаете компоненту Child, используется только как начальное значение для useState hook. При следующих обновлениях useState будет игнорировать это значение, поскольку childValue уже инициализировано. Чтобы обновить переменную состояния childValue, вам нужно использовать useEffect, в котором вам нужно вызвать setChildValue:

const Child = ({value, onChange}) => {
  const [childValue, setChildValue] = React.useState(value !== undefined ? value : 0);

  React.useEffect(() => {
    value !== undefined && setChildValue(value);
  }, [value]);

...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...