简体   繁体   English

如何将值从自定义组件类传递到redux-form?

[英]How to pass value from custom component class to redux-form?

I'm calling a custom component in my redux-form. 我正在以redux形式调用自定义组件。

<Field name="myField" component={SiteProjectSelect}/>

This component is a combination of two combo boxes. 此组件是两个组合框的组合。 The second box is dependant on the value of the first on - ie depending on what site you select, you can choose from a list of projects. 第二个框取决于第一个框的值-即取决于您选择的站点,您可以从项目列表中进行选择。 What I'd like to do is get the form to receive the selected site and the selected projects. 我想做的就是获取表格以接收选定的站点和选定的项目。 However, I'm not sure how to pass the values to the redux-form. 但是,我不确定如何将值传递给redux-form。

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>
        );
    }
}

I did finally figure it out. 我终于确定了。 For anyone else who stumbles across this, here's what I needed to know. 对于偶然发现此问题的其他人,这是我需要知道的。 To use a custom component, 要使用自定义组件,

  • Use the onChange prop to set the new value of the Field. 使用onChange属性设置字段的新值。 You do this by calling the onChange function, this.props.input.onChange(your-components-new-value-here) when you need to change the value of the component and passing it the new value. 当您需要更改组件的值并将新值传递给它时,可以通过调用onChange函数this.props.input.onChange(your-components-new-value-here)来实现。
  • This new value will now be stored in the value prop: this.props.input.value . 现在,此新值将存储在value prop: this.props.input.value So, wherever in the render function for your component you need to pass/display the current value of your component, use the value prop. 因此,无论在组件的渲染功能中需要传递/显示组件当前值的任何地方,都应使用value属性。 It has to be the value prop and not another variable such as what you passed to your onChange function. 它必须是value prop,而不是其他变量,例如您传递给onChange函数的变量。 What this does is give control of what's displayed to the state of your redux-form which the value prop is tied to. 这样做是为了控制显示与value道具绑定到的redux表单的状态。 Why is this useful? 为什么这有用? For example, you could take the user to a form review page when they're done and then back to the form if the user wants to make some more changes. 例如,您可以在用户完成操作后将其带到表单查看页面,然后在用户想要进行更多更改时返回到表单。 How would redux-form know how to repopulate all of what's displayed without getting the user to fill in the form again? redux-form如何知道如何重新填充所有显示的内容,而无需让用户再次填写表单? Because the display is dependant on the state, not user input! 因为显示取决于状态,而不是用户输入! Took me a while to make sense of all this!! 花了我一段时间才能理解所有这些内容!!

In my example, where I was using two react-select components, one of which was dependant on the other, I ended up having to use the Fields component which allowed me to have two Fields in my component rather than just the one. 在我的示例中,当我使用两个react-select组件时,其中一个依赖于另一个组件,最终我不得不使用Fields组件,这使我可以在组件中拥有两个Field,而不仅仅是一个。 Once I implemented this, it also became evident that I didn't need to have a separate state within my component as the value of both Fields is always accessible via the value prop for each of them. 一旦实现了这一点,就很明显我不需要在组件中具有单独的状态,因为两个字段的value始终可以通过它们各自的value属性来访问。 So, yes, I could have just used a stateless function after all! 所以,是的,我毕竟可以只使用无状态功能!

I call my component with: 我用以下方式调用组件:

<Fields names={["site", "projects"]} component={SiteProjectSelect} />

My final working component: 我最后的工作组件:

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>
        );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM