Создана опция выбора из состояния, не обновляющая форму json, если не щелкнуть

У меня есть redux-form и react-select, работая вместе. В response-select есть возможность создавать новую опцию выбора на лету, вводя текст в текстовое поле выбора.

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

Однако это не обновляет мою форму json, пока я не нажму вновь созданную опцию, которая выглядит так, как будто она уже выбрана.

Для репликации: введите в поле выбора - вы заметите, что новая созданная опция выделена и поле выбора обновлено. Но вы также увидите, что значения json остаются неизменными. Нажмите на вновь созданную опцию, вы увидите изменение значений.

Пример Codesandbox: https://codesandbox.io/s/k2v2922nq5

import React from "react";
import { Field, reduxForm, FieldArray } from "redux-form";
import TextField from "material-ui/TextField";
import { RadioButton, RadioButtonGroup } from "material-ui/RadioButton";
import Checkbox from "material-ui/Checkbox";
import SelectField from "material-ui/SelectField";
import MenuItem from "material-ui/MenuItem";
import asyncValidate from "./asyncValidate";
import validate from "./validate";
import CreatableSelect from "react-select/lib/Creatable";
const CustomStyle = {
  option: (base, state) => ({
    ...base,
    display: "inline",
    marginRight: "10px",
    backgroundColor: state.isSelected ? "#00285C" : "#eee",
    cursor: "pointer"
  }),
  menuList: () => ({
    padding: 10,
    display: "inline-flex"
  }),
  menu: () => ({
    position: "relative"
  })
};

const createOption = (label: string) => ({
  label,
  value: label.toLowerCase().replace(/\W/g, "")
});
class LastNameSelectInput extends React.Component {
  constructor(props) {
    super(props);
  }

  state = {
    value: this.props.options[0],
    options: this.props.options
  };
  handleCreate = (inputValue: any) => {
    this.setState({ isLoading: true });
    setTimeout(() => {
      const { options } = this.state;
      const newOption = createOption(inputValue);
      this.setState({
        isLoading: false,
        options: [...options, newOption],
        value: newOption
      });
    }, 1000);
  };
  render() {
    const { input, options } = this.props;
    return (
      <div>
        <style>
          {`.react-select__dropdown-indicator,.react-select__indicator-separator {
          display: none;
        }`}
        </style>
        <CreatableSelect
          classNamePrefix="react-select"
          options={this.state.options}
          menuIsOpen={true}
          onChange={value => {
            let newValue = input.onChange(value);
            this.setState({ value: newValue });
          }}
          onBlur={() => input.onBlur(input.value)}
          onCreateOption={this.handleCreate}
          value={this.state.value}
          styles={CustomStyle}
          isClearable
        />
      </div>
    );
  }
}

const MaterialUiForm = props => {
  const { handleSubmit, options, pristine, reset, submitting } = props;

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <Field name="firstName" component={LastNameSelectInput} {...props} />
      </div>
    </form>
  );
};

export default reduxForm({
  form: "MaterialUiForm", // a unique identifier for this form
  validate,
  asyncValidate
})(MaterialUiForm);

person Tom Rudge    schedule 05.11.2018    source источник
comment
Похоже, вам нужно вручную отправить событие изменения   -  person Mrchief    schedule 05.11.2018


Ответы (1)


Итак, когда вы создаете новую опцию, вы устанавливаете состояние компонента React, но ничего не делаете, чтобы сообщить redux-form, которая использует хранилище Redux в качестве своего состояния. Это всегда большой источник путаницы (состояние компонента React или хранилище Redux).

Решение состоит в том, чтобы сообщить redux-form, что мы также хотим выбрать нашу недавно созданную опцию. Это можно сделать, отправив onChange вручную.

Я разветвил вашу песочницу и добавил отправку вручную.

Заметные изменения (для краткости опущен существующий код):

handleCreate

// takes the input to fire dispatch upon
handleCreate = input => (inputValue: any) => {

...
this.setState(...);
input.onChange(newOption); // manually dispatching the change to let redux-form know

рендерить

// pass a ref to the input in handleCreate
onCreateOption={this.handleCreate(input)}

redux-form позволяет вручную запускать изменить, используя также имя поля, но привязка input является наиболее предпочтительной.

person Mrchief    schedule 05.11.2018
comment
Спасибо, это отличный ответ, и теперь я понимаю. - person Tom Rudge; 05.11.2018