Managing React controlled component state

Phil Parsons

Tagged: ,

React provides two types of text input fields, controlled and uncontrolled components. The value of a controlled component is managed by React and requires that the value property of the component be set and that the component have a handler for managing onChange events. Below is an example of a controlled input field you might typically see used in a form.

Controlled components therefore need to have the value of the field managed somehow. There are two commonly used approaches for this; managing the value inside the component state and managing it within a store when implementing a Flux architecture. The Flux approach can lead to performance issues in the user interface when intermediary actions don’t allow the value to update immediately. We’ll see an exaggerated example here with a username field that contacts a server to check if the username is already in use. The call to the server needs to happen when the field value changes but we don’t want to wait for the response before we update the value in the store and propagate that change to the user interface. Let’s see an example of this using Redux.

This is the top level (Smart) component that manages the application state. When the value of the controlled input component changes the onValueChange action is created and dispatched. This action is asynchronous and causes severe problems with updates to the field. The value is not updated immediately in the store so the field does not show the new value when typing, this also means on subsequent key presses the wrong value is read and previous updates are lost. The code for the action which simulates a call to the server is shown below.

Let’s first look at fixing the issue using the component state so that the value updates are not lost and are reflected in the UI immediately. This approach goes against the grain of having dumb components that only require property updates from a single source of truth, the Flux store.

These changes allow the value to be set initially, be updated by the onChange events in the user interface and have the value updated in subsequent renders from external property changes. But this isn’t what we want in our Flux architecture now, is it?

A better solution to the problem is to identify the two separate actions early and create two distinct data flows. One action to update the value in the store immediately and a second action to make the call to the server. Let’s see what that looks like in the top level component.

And the separate action creators.

You can see that with these changes we are also able to debounce the existing username check so that it only raises the action to call the server after 200ms of inactivity preventing unnecessary network requests.

You can find the full code example on Github and please feel free to leave any questions in the comments.

It's only fair to share...Tweet about this on TwitterShare on FacebookShare on Google+Buffer this pageShare on LinkedInPin on Pinterest

/ 9 Articles

Phil Parsons

Leave a Comment

Your email address will never be published or shared and required fields are marked with an asterisk (*).