3

I've got a child component that has a text input field whose value should be initialized with props from parent component (this.props.index).

This should be controlled input, since I want to be able to store the text of the input.

Now, if I set the value to the state's attribute, whenever the component gets re-rendered, it's never updated, since setState is never called:

<input type={"text"} placeholder={"Index"} className={"form-control"}
                       value={this.state.index} onChange={this.updateStudentIndex}/>

On the other hand, if I set the value to the prop's attribute, it's fixed and changes cannot be made:

<input type={"text"} placeholder={"Index"} className={"form-control"}
                       value={this.props.index} onChange={this.updateStudentIndex}/>

How can I both initialize the state with this.props.index, and still be able to track changes in the input's value this.state.index?

Edit: Initialization should be done in async mode, i.e. when I click a button from the parent component.

4 Answers 4

3

I think default values might be helpful here.

Sign up to request clarification or add additional context in comments.

1 Comment

Nope, this does not help. I got the following error: EditStudentDetails contains an input of type text with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both).
0

If you are familiar with The Component Lifecycle, use componentWillReceiveProps, and set there then new state

componentWillReceiveProps(nextProps) {
   if(this.props.index !== nextProps.index) {
     this.setState({index: nextProps.index})
   }
}

And you can hold your value in state, so on componentWillMount set your state.index to props.index

2 Comments

componentWillUpdate(){ this.setState({index: this.props.index}) } causes Maximum Update Depth Exceeded exception
Isn't componentWillReceiveProps going to be deprecated soon and shouldn't be used?
0

In the constructor read the value from props and set that to state, this way you will get the props.index and maintain the changes in the state afterword. In the onChange event handler you can update index with the current value.

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      index: props.index
    }
  }
  ...
  render() {
    const { index } = this.state;
    ...
  }
}

Hope this will help!

5 Comments

Sadly no, because the constructor is called when the child component is first created, but I need the initializing to be asynchronously, i.e. when I click the button, the input fields are initialized.
Oh, but you didn't mention about asynchronously initializing in the question also nothing about button either :) ...
True, sorry. You got any other solution?
Nope, can you please share more detail, how the parent and child related and when you are initializing the child component. If possible share some code.
I found a solution, it lies with uncontrolled components.
0

Found solution, this should not be done with controlled components, rather uncontrolled components

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.