简体   繁体   English

反应:如何将选择选项值映射到状态键?

[英]React: How to map select option value to a state key?

Currently getting to grips with JS and React. 目前正在使用JS和React。 I want to map the value from the selected option to this.state.transcode_profile . 我想将值从所选选项映射到this.state.transcode_profile I have tried the same method as I am using on the input tags unfortunately this is not working. 不幸的是,我尝试了与在input标签上使用的方法相同的方法。

Here's the code, what am I doing wrong? 这是代码,我在做什么错?

import React, { Component } from "react";

    const ProfileList = ({profiles}) => (
        <select name="transcode_profile"
                id="transcode_profile"
                onChange={this.onChange}>
            <option value="-----">----</option>
            {profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
        </select>
    );

    const url = 'http://localhost:8000/api/tasks/';

    class Submit_job extends Component {

        constructor(){
            super();
            this.state = {
                "profiles": [],
                "material_id": null,
                "transcode_profile": null,
                "start_date": null,
                "end_date": null,
            };
        };

        componentDidMount(){
            fetch("http://localhost:8000/api/profiles/")
                .then(response => response.json())
                .then(response => this.setState({ profiles: response}))
        }

        onChange = (e) => {
            // Because we named the inputs to match their corresponding values in state, it's
            // super easy to update the state
            const state = this.state;
            state[e.target.name] = e.target.value;
            this.setState(state);
        };

        handleChange(e){
            this.setState({selectValue:e.target.value});
        };

        postData = (e) => {
            e.preventDefault();
            // Default options are marked with *
            return fetch(url, {
                body: JSON.stringify({status: 'submitted',
                    video_data: {material_id: this.state.material_id},
                    profile_data: {name: this.state.transcode_profile },
                    start: this.state.start_date,
                    end: this.state.end_date,
                    user: 'Foobar'}), // must match 'Content-Type' header
                cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
                credentials: 'same-origin', // include, same-origin, *omit
                headers: {
                    'user-agent': 'Mozilla/4.0 MDN Example',
                    'content-type': 'application/json'
                },
                method: 'POST', // *GET, POST, PUT, DELETE, etc.
                mode: 'cors', // no-cors, cors, *same-origin
                redirect: 'follow', // *manual, follow, error
                referrer: 'no-referrer', // *client, no-referrer
            })
                .then(response => response.json()) // parses response to JSON
        };

        render() {
            return (
                <div>
                    <h2>Submit Job</h2>
                    <form onSubmit={this.postData}>
                        <label htmlFor="material_d">Material ID:</label>
                        <input id="material_id"
                               type="text"
                               name="material_id"
                               onChange={this.onChange}
                               required/>
                        <br/>
                        <label htmlFor={"transcode_profile"}>Transcode Profile:</label>
                        <ProfileList profiles={this.state.profiles}/>
                        <br/>
                        <label htmlFor="start_date">Start Date:</label>
                        <input type="text"
                               name="start_date"
                               id="start_date"
                               onChange={this.onChange}
                               required/>
                        <br/>
                        <label htmlFor="end_data">End Date:</label>
                        <input type="text"
                               name="end_date"
                               id="end_date"
                               onChange={this.onChange}
                               required/>
                        <br/>

                        <button>Submit</button>
                    </form>

                </div>

            );
        }
    }

    export default Submit_job;

Edit: This is how i got it working. 编辑:这就是我如何使其工作。

import React, { Component } from "react";

const ProfileList = ({onChange, profiles, value}) => (
    <select name="transcode_profile"
            id="transcode_profile"
            onChange={onChange}
            value={value}>
        <option value="-----">----</option>
        {profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
    </select>
);

const url = 'http://localhost:8000/api/tasks/';

class Submit_job extends Component {

    constructor(){
        super();
        this.state = {
            "profiles": [],
            "material_id": null,
            "transcode_profile": null,
            "start_date": null,
            "end_date": null,
        };
    };

    componentDidMount(){
        fetch("http://localhost:8000/api/profiles/")
            .then(response => response.json())
            .then(response => this.setState({ profiles: response}))
    }

    onChange = (e) => {
        // Because we named the inputs to match their corresponding values in state, it's
        // super easy to update the state
        const state = this.state;
        state[e.target.name] = e.target.value;
        this.setState(state);
    };

    postData = (e) => {
        e.preventDefault();
        // Default options are marked with *
        return fetch(url, {
            body: JSON.stringify({status: 'submitted',
                video_data: {material_id: this.state.material_id},
                profile_data: {name: this.state.transcode_profile },
                start: this.state.start_date,
                end: this.state.end_date,
                user: 'Lewis'}), // must match 'Content-Type' header
            cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
            credentials: 'same-origin', // include, same-origin, *omit
            headers: {
                'user-agent': 'Mozilla/4.0 MDN Example',
                'content-type': 'application/json'
            },
            method: 'POST', // *GET, POST, PUT, DELETE, etc.
            mode: 'cors', // no-cors, cors, *same-origin
            redirect: 'follow', // *manual, follow, error
            referrer: 'no-referrer', // *client, no-referrer
        })
            .then(response => response.json()) // parses response to JSON
    };

    render() {
        return (
            <div>
                <h2>Submit Job</h2>
                <form onSubmit={this.postData}>
                    <label htmlFor="material_d">Material ID:</label>
                    <input id="material_id"
                           type="text"
                           name="material_id"
                           onChange={this.onChange}
                           required/>
                    <br/>
                    <label htmlFor={"transcode_profile"}>Transcode Profile:</label>
                    <ProfileList
                        onChange={this.onChange}
                        profiles={this.state.profiles}
                    />
                    <br/>
                    <label htmlFor="start_date">Start Date:</label>
                    <input type="text"
                           name="start_date"
                           id="start_date"
                           onChange={this.onChange}
                           required/>
                    <br/>
                    <label htmlFor="end_data">End Date:</label>
                    <input type="text"
                           name="end_date"
                           id="end_date"
                           onChange={this.onChange}
                           required/>
                    <br/>

                    <button>Submit</button>
                </form>

            </div>

        );
    }
}

export default Submit_job;

The select should be passed the value as well, so it knows which option is selected: 选择也应传递值,以便知道选择了哪个选项:

const ProfileList = ({ onChange, profiles, value }) => (
    <select
      name="transcode_profile"
      id="transcode_profile"
      onChange={onChange}
      value={value}
    >
        <option value="-----">----</option>
        {profiles.map(profile => <option value={profile.name}>{profile.name}</option>)}
    </select>
);

Then when rendering ProfileList, we should pass the selectValue state, as well as the handleChange callback. 然后,在渲染ProfileList时,我们应该传递selectValue状态以及handleChange回调。

<ProfileList 
  onChange={this.handleChange} 
  profiles={this.state.profiles} 
  value={this.state.selectValue} 
/>

You should also set the default state in the constructor as well for selectValue 您还应该在构造函数中为selectValue设置默认状态。

constructor(){
  super();
  this.state = {
    "profiles": [],
    "material_id": null,
    "transcode_profile": null,
    "start_date": null,
    "end_date": null,
    "selectValue": "-----"
  };
}

If you haven't already read the React docs on forms, I would recommend them: https://reactjs.org/docs/forms.html#the-select-tag 如果您尚未阅读表格上的React文档,我会推荐它们: https : //reactjs.org/docs/forms.html#the-select-tag

 handleChange = (e, {value}) => {
  this.setState({selectValue:value});
 };

this can also be written as 这也可以写成

handleChange = (e, data) => {
  this.setState({selectValue:data.value});
};

For some elements Semantic-UI-React requires you to provide the event first but also a second argument which contains the data you need. 对于某些元素,Semantic-UI-React要求您首先提供事件,但还需要提供包含所需数据的第二个参数。 It is a well known limitation. 这是一个众所周知的限制。

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

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