从不更新表单 json 的状态创建 select 选项,除非单击
Created select option from state not updating form json unless clicked
我有一个 redux-form and react-select 一起工作。 react-select 能够通过在 select 文本字段中输入来即时创建新的 select 选项。
在我的示例中,您会看到我更新了视图,以便新创建的选项突出显示为 selected 并出现在 select 字段中。
但是,这不会更新我的表单 json,除非我单击看起来已经 select 的新创建的选项。
要复制:在 select 框中键入 - 您会注意到新创建的选项已突出显示并且 select 字段已更新。但您还会看到 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);
因此,当您创建一个新选项时,您正在设置 React 组件状态,但没有做任何事情让 redux-form 知道,它使用 Redux 存储作为其状态。这始终是一个很大的混淆来源(React 组件状态与 Redux 存储)。
解决方案是让 redux-form 知道我们想要 select 我们新创建的选项。这可以通过手动调度 onChange
来完成。
我 forked 您的沙盒并添加了手动调度。
显着变化(为简洁起见省略现有代码):
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 让您也可以使用字段名称手动触发 change,但绑定 input
是最可取的。
我有一个 redux-form and react-select 一起工作。 react-select 能够通过在 select 文本字段中输入来即时创建新的 select 选项。
在我的示例中,您会看到我更新了视图,以便新创建的选项突出显示为 selected 并出现在 select 字段中。
但是,这不会更新我的表单 json,除非我单击看起来已经 select 的新创建的选项。
要复制:在 select 框中键入 - 您会注意到新创建的选项已突出显示并且 select 字段已更新。但您还会看到 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);
因此,当您创建一个新选项时,您正在设置 React 组件状态,但没有做任何事情让 redux-form 知道,它使用 Redux 存储作为其状态。这始终是一个很大的混淆来源(React 组件状态与 Redux 存储)。
解决方案是让 redux-form 知道我们想要 select 我们新创建的选项。这可以通过手动调度 onChange
来完成。
我 forked 您的沙盒并添加了手动调度。
显着变化(为简洁起见省略现有代码):
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 让您也可以使用字段名称手动触发 change,但绑定 input
是最可取的。