Элемент раскрывающегося (выбранного) пользовательского интерфейса материала не обновляется в onChange в динамической форме - PullRequest
1 голос
/ 23 сентября 2019

Я создаю динамическую форму, которая загружает некоторые дополнительные поля через JSON.Моя проблема заключается в том, что элементы и не перерисовываются после изменения значения.Моя форма в настоящее время является функциональным компонентом.Как создать хуки на лету (с помощью useState), чтобы при запуске onChange эти поля корректно обновлялись и перерисовывались.

Я сохраняю обновленные значения в словаре, и при отправке я вижу значениябыли обновлены.Странно то, что я использую точно такой же процесс, используя элементы, и они хорошо рендерится.Это как-то неконтролируемые?Могу ли я обновить элементы вне использования useState?

Я попытался инициализировать переменную словаря как пустой словарь, используя useState, но могу ли я добавить к нему ключи и значения и вызвать повторную визуализацию?

Пожалуйста, посмотрите мой код на https://codesandbox.io/s/competent-mendel-q51ld

Редактировать:

Кажется, он не связан с хуками React (я пытался использовать те, которые были созданы, когда компонентвпервые используется).Я думаю, что проблема заключается в элементах <Select> и <Radio>.Если они создаются программно после первого рендеринга компонента, они не обновляются даже при обновлении связанных с ними переменных состояния.<Text> элементы обновляются нормально, и они обновляются по тому же механизму.

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

Обновление:

Это определенно проблема с элементами <Select> и <Radio>, так как обычные выпадающие списки HTML и радио обновляются нормально.

1 Ответ

1 голос
/ 23 сентября 2019

Проблема заключается в том, что вы запускаете рендеринг каждый раз при вызове setState, что вызывает неконтролируемое состояние состояния :) Вам необходимо заменить useState на useReducer .Таким образом, вы сможете обновить весь набор свойств за один повторный рендеринг.Чтобы использовать useReducer, вам нужно написать редуктор раньше.

function reducer(state, action) {
  switch (action.type) {
    case 'YOUR_ACTION_TYPE':
    return {
      ...state,
      extraCarFields: false,
      extraOtherFields: true,
      extraOtherFieldsData: action.extraFields
      finalCategory: value
    };
    default:
      throw new Error();
  }
}

После этого инициализируйте его

const [state, dispatch] = useReducer(reducer, initialState);

Тогда, например, вместо

setState(prevState => ({ ...prevState, extraCarFields: false }))
setState(prevState => ({ ...prevState, extraOtherFields: true }))
setState(prevState => ({ ...prevState, extraOtherFieldsData: loadExtraFields(otherFields) }))
setState(prevState => ({ ...prevState, finalCategory: value }))

Вы будетеdo

const extraFields = loadExtraFields(otherFields);
dispatch({ type: "YOUR_ACTION_TYPE", extraFields: extraFields });

Также рекомендую прочитать обо всех доступных стандартных крючках .Я думаю, что вы, вероятно, будете использовать useCallback для запоминания ваших функций, а не для инициализации их при каждом рендеринге.И вторая рекомендация - перейти к async , ожидать , чтобы выполнить правильное поведение при загрузке ExtraFields перед отправкой обновления в состояние.

ОБНОВЛЕНИЕ

Для обновления значений в форме я использую такой шаблон:

const reducer = (state, action) => {
  switch (action.type) {
    case "UPDATE_FIELD":
      return {
        ...state,
        [action.prop]: action.value
      };
    default:
      return state;
  }
};

...

const handleChange = prop => e => {
  const { value } = e.target;
  dispatch({ type: "UPDATE_FIELD", prop: prop, value: value });
};

...

<TextField
      label="Your email address"
      name="email"
      type="email"
      value={state.email}
      onChange={handleChange('email')}
      required autoFocus fullWidth />

Таким образом, вы просто передаете имя вашей собственности handleChangefunction и json magic сделают все остальное :) Не стесняйтесь задавать дополнительные вопросы, если я что-то пропустил.

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