Условные выпадающие списки с реакции-выбора в реакции-окончательной форме, инициализированные из состояния - PullRequest
2 голосов
/ 09 ноября 2019

Я использую react-select и react-final-form для условных выпадающих меню, где опции для второго выбора предоставляются компонентом <PickOptions/> на основе значения первого выбора (благодаря этому SO answer ).

Вот компонент:

/** Changes options and clears field B when field A changes */
const PickOptions = ({ a, b, optionsMap, children }) => {
  const aField = useField(a, { subscription: { value: 1 } });
  const bField = useField(b, { subscription: {} });
  const aValue = aField.input.value.value;
  const changeB = bField.input.onChange;
  const [options, setOptions] = React.useState(optionsMap[aValue]);

  React.useEffect(() => {
    changeB(undefined); // clear B
    setOptions(optionsMap[aValue]);
  }, [aValue, changeB, optionsMap]);
  return children(options || []);
};

Сбрасывает второй выбор, когда значение первого изменяется на changeB(undefined). Я также установил второй выбор к первому параметру в массиве, передав initialValue. Поскольку мне нужно инициализировать значения из состояния, я получил следующий код:

initialValue={
  this.state.data.options[index] &&
  this.state.data.options[index].secondOption
    ? this.state.data.options[index]
        .secondOption
    : options.filter(
        option => option.type === "option"
      )[0]
}

Но это не работает. Начальные значения из состояния не передаются в поля, представленные <PickOptions/>. Если я удаляю changeB(undefined) из компонента, значения передаются, но затем входное значение второго выбора не обновляется, когда изменяется значение первого выбора (даже если параметры были обновлены). Вот ссылка на мои коды и коробку .

Как это исправить?

1 Ответ

0 голосов
/ 15 ноября 2019

Я смог заставить это работать, взяв все, что отображается в разделе fields.map(), и обернул его в свой собственный компонент, чтобы гарантировать, что у каждого из них есть отдельные состояния. Затем я просто помещаю функцию changeB(undefined) в ответный вызов хука useEffect, чтобы очистить вторичные выборки после того, как пользователь выбирает другую опцию для первого выбора, например, так:

React.useEffect(() => {
  setOptions(optionsMap[aValue]);

  return function cleanup() {
    changeB(undefined) // clear B
  };
}, [aValue, changeB, optionsMap]);

Вы можете видетькак это работает в этой изолированной программной среде: Реакция окончательной формы - Очистка вторичного выбора .

Чтобы изменить вторичные поля выбора, вам нужно будет передать дополнительную подпорку в PickOptions для типаОпция, которой соответствует массив. Я также подписываюсь и отслеживаю предыдущий bValue, чтобы проверить, существует ли он в текущем массиве bValueSet. Если он существует, мы оставляем его в покое, в противном случае мы обновляем его первым значением в соответствующем массиве optionType.

  // subscibe to keep track of previous bValue
  const bFieldSubscription = useField(b, { subscription: { value: 1 } })
  const bValue = bFieldSubscription.input.value.value

  React.useEffect(() => {
    setOptions(optionsMap[aValue]);

    if (optionsMap[aValue]) {
      // set of bValues defined in array
      const bValueSet = optionsMap[aValue].filter(x => x.type === optionType);

      // if the previous bValue does not exist in the current bValueSet then changeB
      if (!bValueSet.some(x => x.value === bValue)) {
        changeB(bValueSet[0]); // change B
      }
    }

  }, [aValue, changeB, optionsMap]);

Вот песочница для этого метода: React Final Form - UpdateSecondary Selects .

Я также изменил ваш компонент класса на функционал, потому что мне было легче видеть и тестировать, что происходит, но этот метод должен также работать с вашим компонентом класса.

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