Skip to content

Bidirectional data in multi‐part nested react components

David edited this page Aug 19, 2024 · 1 revision

The challenge is that data can come down from the database to be shown to the user, and the user can enter data that needs to go up to the database. If not done right, it's easy to create an infinite loop.

Think of a google doc where the user can enter data, and it goes up to the cloud and gets saved, but also other users can edit the doc, so changes have to come back down to the user). Except in this case there is more structure to the data than just a free form doc.

image

The problem is that it's easy to end up with a loop where the data goes down to the input component, and the change causes the input form to send data up to the top component, which rerenders because of the change, which causes the data to go down to the input component.

One other complication is that we are doing input validation at the bottom, and passing the valid state up for use at higher levels of the UI.

<Component onDone({valid, value}) ...otherProps />

In order to pass data up to parent React components, we use a pattern of passing down a function, onDone. The child component will call onDone when data has changed, passing both the value of the data, and the valid state of the data.

At the top level: We are rendering a list of the same component, but we can keep track of the different components by an id in the data. (parentId in the case of WhyStep) If data comes down from the API/Database apply the change to the state, using the setter. Keep track of the data in a state. If data comes up from the UI, mutate the state object directly so that a rerender is not caused. Keep track of the valid information in an object, but never use the setter to cause a rerender.

At the bottom level, we need to use value (rather than defalultValue) in the input field, so that what's shown to the user can be changed both by user input, and by new data in props.

Clone this wiki locally