我正在以redux形式调用自定义组件。
<Field name="myField" component={SiteProjectSelect}/>
此组件是两个组合框的组合。第二个框取决于第一个框的值-即取决于您选择的站点,您可以从项目列表中进行选择。我想做的就是获取表格以接收选定的站点和选定的项目。但是,我不确定如何将值传递给redux表单。
class SiteProjectSelect extends Component {
constructor() {
super();
this.state = {
selectedSite: null,
selectedProject: null,
};
}
handleSiteSelection = selectedSite => {
console.log(selectedSite)
this.setState({ selectedSite, selectedProject: null });
};
handleProjectSelection = selectedProject => {
this.setState({ selectedProject });
this.props.input.onChange(selectedProject.value);
};
render() {
const selectedRow = this.state.selectedSite ? projects.find((node) => node.site === this.state.selectedSite.value) : "";
const filteredProjectOptions = selectedRow ? selectedRow.projects.map(project => ({ value: project, label: project })) : []
return (
<div {...this.props} >
<label>Site</label>
<div style={{ marginBottom: '20px' }} >
<Select
name="site"
value={this.state.selectedSite}
onChange={this.handleSiteSelection}
options={siteOptions}
isSearchable
/>
</div>
<div style={{ marginBottom: '20px' }} >
<label>Project</label>
<Select
name="project"
value={this.state.selectedProject}
onChange={this.handleProjectSelection}
options={filteredProjectOptions}
isMulti
isSearchable
closeMenuOnSelect={false}
/>
</div>
</div>
);
}
}
答案 0 :(得分:1)
我终于弄清楚了。对于偶然发现此问题的其他人,这是我需要知道的。要使用自定义组件,
onChange
道具设置字段的新值。为此,您可以在需要更改组件的值并将新值传递给它时,调用onChange
函数this.props.input.onChange(your-components-new-value-here)
。value
属性this.props.input.value
中。因此,无论在组件的渲染功能中需要传递/显示组件当前值的任何地方,都应使用value
属性。它必须是value
属性,而不是其他变量,例如您传递给onChange函数的变量。这样做是为了控制与value
属性绑定的redux-form的状态所显示的内容。为什么这有用?例如,您可以在用户完成操作后将其带到表单查看页面,然后在用户想要进行更多更改时返回到表单。 redux-form如何知道如何重新填充所有显示的内容,而无需让用户再次填写表单?因为显示取决于状态,而不是用户输入!花了我一段时间才能理解所有这些内容!在我的示例中,当我使用两个react-select
组件时,其中一个依赖于另一个组件,我最终不得不使用Fields组件,该组件使我可以在我的两个字段中使用组件,而不只是一个组件。一旦实现了这一点,就很明显我不需要在组件中具有单独的状态,因为两个字段的值始终可以通过value
属性访问它们中的每个字段。所以,是的,我毕竟可以使用无状态功能!
我通过以下方式调用组件
: <Fields names={["site", "projects"]} component={SiteProjectSelect} />
我最后的工作组件:
class SiteProjectSelect extends Component {
handleSiteSelection = selectedSite => {
this.props.site.input.onChange(selectedSite);
this.props.projects.input.onChange(null);
};
handleProjectSelection = selectedProjects => {
this.props.projects.input.onChange(selectedProjects);
};
renderSite = () => {
const {
input: { value },
meta: { error, touched }
} = this.props.site;
return (
<div>
<label>Site</label>
<div style={{ marginBottom: '20px' }}>
<Select
name="site"
value={value}
onChange={this.handleSiteSelection}
options={siteOptions}
isSearchable
/>
</div>
<div className="red-text" style={{ marginBottom: '20px' }}>
{touched && error}
</div>
</div>
);
};
renderProjects = () => {
var {
input: { value },
meta: { error, touched }
} = this.props.projects;
const selectedSite = this.props.site.input.value;
const selectedRow = selectedSite
? projects.find(node => node.site === selectedSite.value)
: '';
const filteredProjectOptions = selectedRow
? selectedRow.projects.map(project => ({
value: project,
label: project
}))
: [];
return (
<div>
<div style={{ marginBottom: '20px' }}>
<label>Projects</label>
<Select
name="projects"
value={value}
onChange={this.handleProjectSelection}
options={filteredProjectOptions}
isMulti
isSearchable
closeMenuOnSelect={false}
/>
</div>
<div className="red-text" style={{ marginBottom: '20px' }}>
{touched && error}
</div>
</div>
);
};
render() {
return (
<div>
{this.renderSite()}
{this.renderProjects()}
</div>
);
}
}