Jasper
Jasper

Reputation: 2231

React: setting state and default input from prop

I'm creating a app that allows users to create assessments (that other users can complete). Right now I am working on an 'edit' page, where a users loads a form that is prefilled with the relevant data - but he is then able to change these values.

However, I am having trouble with two things (that I suspect are related). First: the input fields wont display a default value that is derived from the component state.

Second: If I set the input fields directly from the props I am no longer able to change the values.

The components gets passed a prop that is called block_data which is a dict containing key/value pairs of strings.

I'm attempting to convert load it into the state like so

constructor(props) {
    super(props);

    this.state = {
        block: this.props.block_data,
        question_list: [],
        question_options: ['BO', 'SC', 'SR', 'NO'],
        block_list: [],
    };
    (..)
}

However, this does not work. When I check in the chrome react extension the state is not set.

The input fields are all very simular to the example I've included below. Here I've set its value from the props. In this case it does display the correct initial data. But I am unable to edit it.

<input 
  onChange={e => this.changeIsANaturalPartOfLife(e)}
  value={this.props.block_data.title}
  name="title"
  />

Below is the 'on change' function. When I check the chrome react tool, I can see that only the first letter of the state is updated when I start typing. The input field does not show any changes.

changeIsANaturalPartOfLife(e, optional) {

    const target = e.target;
    const name = target.name;
    const value = target.value;
    console.log(value);
    this.setState({ block: {[name]: value }});

}

I am really at a loss here on what to do. What I am trying to do here seems simple enough, yet I'm unable to advance beyond this flawed stage. Does anyone have an idea what I am doing wrong?

Upvotes: 3

Views: 1896

Answers (1)

Mayank Shukla
Mayank Shukla

Reputation: 104499

As you mentioned in comment: "the data is loaded from a DjangoRestAPI".

Solution of first problem:

You need to use componentwillreceiveprops lifecycle method to update the state with new props values (after successfully fetched from server) otherwise state of child component will always have the initial data of parent component.

As per DOC:

componentWillReceiveProps() is invoked before a mounted component receives new props. If you need to update the state in response to prop changes (for example, to reset it), you may compare this.props and nextProps and perform state transitions using this.setState() in this method.

Use this method:

componentwillreceiveprops(nextProps) {
   // compare nextProps.block_data and this.state.block if not equal
   this.setState({
       block: nextProps.block_data
   })
}

Solution of second problem:

When you are directly using the props instead of storing into state, then you need to update the value in parent component during onChange, because you are using this.props.value and updating this.state.value, and hence props.value will always be same and it will not allow you to type anything.

Upvotes: 3

Related Questions