简体   繁体   中英

How can I force re-render input fields in a form in React?

I am trying to create a form where the user can edit the information of a contact from a database and then save those changes. The form correctly loads and saves the information from the database, but when componentDidMount() loads the current information into the form fields, the fields don't re-render, causing both the template text (ie. Name, Email, etc) and the information loaded from the database to display on top of each other. Clicking any of the input fields causes the field that was clicked to render properly with the text displaying above the input field, rather than over the loaded text.

How can I force the form to rerender each field after the data has been loaded properly in componentDidMount()? I've tried forceUpdate() but it didn't work, and I haven't been able to find anyone else with this issue. I suspect it has something to do with me using the bootstrap styles wrong, but even after reading all of bootstrap's documentation I couldn't find anything related to my issue.

Here are a couple of screenshots to show the issue.

The form right after loading

加载后的表单

The form after clicking the 'Name' field

单击“名称”字段后的表单

Here's the relevant code for the component.

    constructor(props) {
        super(props);

        this.state = {
            name: "",
            email: "",
            role: "",
            phone: "",
            errors: {}
        }
    }

    // Initializer: Copy contact's current data to state
    componentDidMount() {
        axios.get("/api/contacts/get/" + this.props.match.params.id)
            .then(res => {
                this.setState({ name: res.data.name });
                this.setState({ email: res.data.email });
                this.setState({ role: res.data.role });
                this.setState({ phone: res.data.phone });
            })
            .catch(err => console.log(err));

        this.forceUpdate();
    }

    // Change handler: Modify values when changed
    onChange = e => {
        this.setState({ [e.target.id]: e.target.value });
    }

    // Submit handler: Save changes to database
    onSubmit = e => {
        e.preventDefault();

        const contact = {
            name: this.state.name,
            email: this.state.email,
            role: this.state.role,
            phone: stripNumber(this.state.phone)
        };

        // Post modified contact to database, then navigate back to Manage Contacts Dashboard
        axios.post("/api/admin/contacts/update/" + this.props.match.params.id, contact);
        window.location = PREVIOUS_URL;
    }

    render() {
        const { errors } = this.state;

        return (
            <div>
                <Link to={PREVIOUS_URL} className="btn-flat waves-effect">
                    <i className="material-icons left">keyboard_backspace</i> Back to Manage Contacts
                </Link>
                <h3>Edit contact</h3>
                <form noValidate onSubmit={this.onSubmit}>
                    <div className="input-field col s12">
                        <input
                            onChange={this.onChange}
                            value={this.state.name}
                            error={errors.name}
                            id="name"
                            type="text"
                            className={classnames("", { invalid: errors.name })}
                        />
                        <label htmlFor="name">Name</label>
                        <span className="red-text">{errors.name}</span>
                    </div>
                    <div className="input-field col s12">
                        <input
                            onChange={this.onChange}
                            value={this.state.email}
                            error={errors.email}
                            id="email"
                            type="email"
                            className={classnames("", { invalid: errors.email || errors.emailnotfound })}
                        />
                        <label htmlFor="email">Email</label>
                        <span className="red-text">{errors.email}{errors.emailnotfound}</span>
                    </div>
                    <div className="input-field col s12">
                        <input
                            onChange={this.onChange}
                            value={this.state.role}
                            error={errors.role}
                            id="role"
                            type="text"
                            className={classnames("", { invalid: errors.role })}
                        />
                        <label htmlFor="role">Role</label>
                        <span className="red-text">{errors.role}</span>
                    </div>
                    <div className="input-field col s12">
                        <input
                            onChange={this.onChange}
                            value={this.state.phone}
                            error={errors.phone}
                            id="phone"
                            type="tel"
                            className={classnames("", { invalid: errors.phone })}
                        />
                        <label htmlFor="phone">Phone Number</label>
                        <span className="red-text">{errors.phone}</span>
                    </div>
                    <div className="form-group">
                        <input type="submit" value="Submit changes" className="btn btn-primary" />
                        <Link to={PREVIOUS_URL} className="btn btn-danger">  Cancel  </Link>
                    </div>
                </form>
            </div>
        )
    }
}

Have you tried doing the data fetch inside componentWillMount() ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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