0

I'm making a little blog in React and I have a problem updating the state on input change event.

The warning is:

Warning: A component is changing a controlled input of type text to be uncontrolled. Input elements should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component

This is my code:

Constructor:

constructor(props){
        super(props);

        this.state = {
            id: '',
            post: {
                title: '',
                slug: '',
                content: ''
            }
        }

        this.handleChange = this.handleChange.bind(this);

    }

handleChange function

handleChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({
            post: {
                [name]: value
            }
        });
    }

input render:

render(){
        return (
            <div>
                <AdminMenu />
                <div id="admin-post-form">
                    <div className="input-group vertical">
                        <label>Título</label>
                        <input
                            name="title"
                            placeholder="Título"
                            type="text"
                            value={this.state.post.title}
                            onChange={this.handleChange}
                        />
                    </div>
                    <div className="input-group vertical">
                        <label>Slug</label>
                        <input
                            name="slug"
                            placeholder="Slug"
                            type="text"
                            value={this.state.post.slug}
                            onChange={this.handleChange}
                        />
                    </div>

                </div>
            </div>
        )
    }

What's wrong with my code ? The field is updated, but I get that warning.

Thanks!

1

3 Answers 3

9

This:

    this.setState({
        post: {
            [name]: value
        }
    });

will replace this.state.post completely with an object that only has a single key. For example, if name is slug, you will replace post with { slug: 'something' }.

As a result, if you edit one field, all other fields will become undefined. React treats value={undefined} as an uncontrolled component and warns you.

To fix the issue, you probably want to merge post updates with the existing object instead of replacing it:

    this.setState(prevState => ({
        post: {
            ...prevState.post,
            [name]: value
        }
    }));
Sign up to request clarification or add additional context in comments.

1 Comment

Is prevState a built-in function or a reserved keyword?
1

Your set state is resetting the whole post object. You likely want to do something like:

this.setState({
    post: {
        ...this.state.post
        [name]: value
    }
})

Comments

0

Solved using spread operator, this is the updated handleChange function that works with nested property:

handleChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        var post = {...this.state.post}
        post[name] = value;
        this.setState({post});
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.