Comments (7)
Not directly related to immutability, but a popular way to improve performance / UX of React applications is to optimize rendering using the shouldComponentUpdate
lifecycle method. Right now, every time the top-level form sets a new state or receives new props, every component in its tree is re-rendering. This means all render logic is called and then React runs its internal virtual DOM diff to see what, if any, browser DOM operations it needs to make. There are many circumstances when you actually do need to re-render based on changes to props or state, but maybe there are some in which you do not want a re-render to trigger. For instance, maybe the form does not need to re-render on changes related to touched
? If there are no UI changes needed, you probably don't need to re-render.
You could also consider similarly optimizing your "helper" components (FormError
, etc). Right now they are implemented as functional stateless components, but each of them is re-rendering whenever the parent form re-renders. It is not a huge lift since these are mostly simple components but it's something to consider. And if the user passes some massively complex component to your Form wrapper, that too will re-render (though that component itself could implement this optimization).
I also notice React has introduced a PureComponent
which has a shallow state / props comparison built into shouldComponentUpdate
to provide some out-of-box performance optimization. I haven't yet used this feature myself though.
EDIT: thinking about it more, actually this concern could be largely obviated by the user just including shouldComponentUpdate
optimization on the wrapped component. So maybe this isn't high priority as an enhancement.
from form.
That's a great start for sure. I've never used PurComponent's either, and judging by the reliance on the deeper data structures, it might produce some false negatives if we did use it.
I know this is one of the tipping points that redux-form had where they were supplying many props (much like react-form does) to the child component that renders the form. Because of this pattern, the child component had to update even if only one field in the values object changed. I imagine this is why they moved to a 100% opt-in value subscription and field wrapper mentality.
It might be challenging to find the middle ground, but right now I feel that the easy access to the state values via props is more valuable in comparison to the edge case performance benefits that a value subscription pattern gives.
What do you think?
from form.
I think you are right, it's probably not worth it at this point. The Form
's own render logic is actually pretty light, it's more a concern of how complex the downstream components are, which can be more granularly controlled if they implement shouldComponentUpdate
.
What might be cool though to try is taking some hard measurements, and then you can see how performance changes as the wrapped component varies in complexity, and also sanity-check that future enhancements to your code don't tank performance.
You could utilize benchmark.js, enzyme, and jsdom to create a suite of tests in which the React components mount to a virtual DOM. I haven't actually ever set this up successfully but I imagine someone has. I might try playing with it later on.
from form.
One compromise I am imagining is possibly putting all of the formstate props behind their own subscriber components permanently. It would be similar in spirit to redux-form's approach, but instead of needing to write lengthy selectors, you would be referencing values much closer to home.
imagine:
Form()(({values}) => {
return (
<form>
<FormInput field='something'/>
{values.friends.map((friends, i) => (
<div key={i}>
<Text
field={['friends', i, 'name']}
placeholder='Friend Name'
/>
</div>
))}
</form>
)
})
// becomes
Form()(() => {
return (
<form>
<FormInput field='something'/>
<FormValue field='friends'>
{(friends) => (
friends.map((friends, i) => (
<div key={i}>
<Text
field={['friends', i, 'name']}
placeholder='Friend Name'
/>
</div>
))
})}
</FormValue>
</form>
)
})
from form.
That would allow the main form component to be treated as pure, unless it's own props change :)
from form.
I'm trying to find any other props the form passes down that would need to be placed behind a subscriber component if we took this approach...
from form.
This might take some more thinking and discover as the library matures. For now, everything works and performance is on par with what is expected from React. Closing until it becomes a real issue.
from form.
Related Issues (20)
- [Docs] Guide page about getting and setting field values HOT 1
- [Docs] Guide about custom form controls HOT 2
- [Tracking] SSR & RSC Usage HOT 5
- [Docs] Guide about dynamic forms & nested fields HOT 1
- [Docs] “Fix” the framework dropdown HOT 1
- [Docs] Update the page title HOT 2
- If validation fails in `onSubmitAsync`, error does not resolve with a valid input HOT 3
- formAPI's onChange not called HOT 1
- onChange and onBlur validation errors should prevent submission of form HOT 9
- Rename Validators to Avoid DOM Event Confusion HOT 2
- Add docs and tests for Field Arrays HOT 5
- FormApi.reset seems to break a form HOT 7
- Unmounting a field does not update the form HOT 1
- Caching Primitives HOT 1
- Mark internal methods as internal HOT 2
- deleteField does not work inside if field is inside an array
- Add tests for getBy, setBy and deleteBy
- Svelte support
- validateAllFields isn't working with touched fields HOT 5
- "A component is changing a controlled input to be uncontrolled" in Next.js App router HOT 5
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from form.