Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating state on props change in React Form

Tags:

reactjs

People also ask

What happens when props change React?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.

How do you update existing state in React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.

Is it possible to change props value in React?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.

What happens when state updates in React?

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.


componentWillReceiveProps is depcricated since react 16: use getDerivedStateFromProps instead

If I understand correctly, you have a parent component that is passing start_time down to the ModalBody component which assigns it to its own state? And you want to update that time from the parent, not a child component.

React has some tips on dealing with this scenario. (Note, this is an old article that has since been removed from the web. Here's a link to the current doc on component props).

Using props to generate state in getInitialState often leads to duplication of "source of truth", i.e. where the real data is. This is because getInitialState is only invoked when the component is first created.

Whenever possible, compute values on-the-fly to ensure that they don't get out of sync later on and cause maintenance trouble.

Basically, whenever you assign parent's props to a child's state the render method isn't always called on prop update. You have to invoke it manually, using the componentWillReceiveProps method.

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}

Apparently things are changing.... getDerivedStateFromProps() is now the preferred function.

class Component extends React.Component {
  static getDerivedStateFromProps(props, current_state) {
    if (current_state.value !== props.value) {
      return {
        value: props.value,
        computed_prop: heavy_computation(props.value)
      }
    }
    return null
  }
}

(above code by danburzo @ github )


componentWillReceiveProps is being deprecated because using it "often leads to bugs and inconsistencies".

If something changes from the outside, consider resetting the child component entirely with key.

Providing a key prop to the child component makes sure that whenever the value of key changes from the outside, this component is re-rendered. E.g.,

<EmailInput
  defaultEmail={this.props.user.email}
  key={this.props.user.id}
/>

On its performance:

While this may sound slow, the performance difference is usually insignificant. Using a key can even be faster if the components have heavy logic that runs on updates since diffing gets bypassed for that subtree.


The new hooks way of doing this is to use useEffect instead of componentWillReceiveProps the old way:

componentWillReceiveProps(nextProps) {
  // You don't have to do this check first, but it can help prevent an unneeded render
  if (nextProps.startTime !== this.state.startTime) {
    this.setState({ startTime: nextProps.startTime });
  }
}

becomes the following in a functional hooks driven component:

// store the startTime prop in local state
const [startTime, setStartTime] = useState(props.startTime)
// 
useEffect(() => {
  if (props.startTime !== startTime) {
    setStartTime(props.startTime);
  }
}, [props.startTime]);

we set the state using setState, using useEffect we check for changes to the specified prop, and take the action to update the state on change of the prop.