Oleksandr Papchenko
Oleksandr Papchenko

Reputation: 2211

How to perform child component validation without infinite loop in react.js

I have really simple example in react. Parent component pass data to the child component throug props. Inside child component i can change this data, also new data can be passed to the child component from the parent at any time. Also on the parent i have save button. After pressing it i should show validation message if some validations did not pass. I have implemented it in such a way. From parent i pass callback to notify parent that validity of the data has changed. Inside child i perform validation in three places:

As you can see there is infinite loop - because React call componentWillReceiveProps in not too smart way - every render cycle instead of callind it only when props actually changed. I am really would like to know what is the react way to solve this issue. Should i store child state only in child ? I also tried to store child validity in parent out of state - but my coworkers said that this is not react way - why ?

Upvotes: 2

Views: 3412

Answers (1)

wintvelt
wintvelt

Reputation: 14101

Here's how I see your challenge:

  • you want to have your validation method in your child component, because it is specific to this type of child (e.g. a password input field). - but in react, no outside component (except grandchildren) are allowed to directly call this method.
  • you want your parent to know about the validaty of each of the children components (e.g. to determine of all the fields validate and a form submit is allowed) - so you need the result of the validation method in the parent component, and this must be state

Your co-workers are correct: react does not like you storing component-wide variables outside of state. Because such variables are completely independent from react lifecycle methods etc. and would get you in debugging hell quickly.

I would advise you to make following changes to prevent the endless loop:

  • do NOT store the validity of the child in the child state. Save the result + any message in the parent, and pass it as a props to the child. Child only renders the props.
  • implement shouldComponentUpdate(), which checks if any of the props or state variables have changed. If not return false, otherwise, return true.
  • move your call to validate() from componentWillReceiveProps to componentWillUpdate(). This ìs called after shouldComponentUpdate(). So only if props or child state have changed, will validation (and re-render) take place.

Upvotes: 2

Related Questions