Performance implications of implementing 2-way data binding in React Performance implications of implementing 2-way data binding in React reactjs reactjs

Performance implications of implementing 2-way data binding in React


2 way data binding implications

Starting from the first part of your question, there are two primary reasons for react not going with two way data binding:

  1. A single source of truth for data changes in a React app, hence less chances of bugs and easier debugging
  2. Performance benefits

In React, we can share state among different child components by lifting the state up to a common parent component. When a shared piece of state is updated, all the child components can update themselves. Here is a good example from the docs related to forms.

Talking about the performance benefits, two way data binding in some other context (say AngularJS) works by means of watchers watching different elements. This sounds easier (and less code than React's one way data flow) for a small number of elements, however as the number of your UI components/elements grow, so does the number of watchers. A single change in this case causes a lot of watchers to fire up in order to keep things in sync. This makes the performance a bit sluggish. In case of React, since there is only one way data flow, it's easier to determine which components need to be updated.

Handling state updates

Coming to the second part of your question, your state library provides the data to your form components causing any dependent components to update on state change, sweet. Here are my thoughts:

I was thinking about allowing individual fields to opt-out of that behavior in case the programmer was concerned about performance, but then I started wondering when this would ever be a real performance issue.

The store update in itself will happen pretty quick. JavaScript runs very fast, it's the DOM updates which often times causes bottlenecks. So, unless there are hundreds of dependent form elements on the same page and all of them are getting updated, you'll be just fine.

And let's suppose that I weren't using apollo but just calling a function that updates some global store directly - what would be the performance consideration then?

I don't think it'll have significant difference.

My thinking is that if a form is going to support immediately updating the form state as the user types in one field, it might as well do so for all the fields. The user can only type in one field at a time, and I don't see the benefit of making the page sometimes faster (probably negligibly) with some fields and sometimes slower with others.

Agreed with this.

My library allows consumers to use whatever input components they want, so if the programmer just wants fewer state updates, they could just write a component that debounces React's onChange event or uses the browser's own change or blur event instead.

I think most of the use cases would be solved with a simple input. Again, I don't see a performance benefit with fewer state updates here. Debounce could be useful if for example I'm running an API call on the input (and want to wait before the user stops typing).

Is there some other reason why a user of my library would want to ignore changes for particular fields until the user submits the form? Or maybe a more useful option would be to ignore changes for the entire form (until submit)?

I don't see a benefit in ignoring changes for a particular field or waiting until submit. On the other hand, when using forms, a common use case I come across implementing things is data validation. For example,

  • provide feedback to the user as and when he is creating a password
  • check if an email is valid
  • perform API calls to see if a username is valid, etc.

These cases would need the state to be updated as the user is typing.

tl;dr

You should be fine with updating state as the user is typing. If you're still concerned about performance, I would suggest to profile your components to isolate bottlenecks if any :)