I'm switching from angularjs to react, and still learning the basic philosophy behind react.
I ran into an issue trying to bind an input element to a property on a model. I first tried using useReducer
, which worked fine to update the model. The problem is that it does not trigger a re-render of the component, since the model is still the same model, just with an updated property. As far as react is concerned, nothing has changed, so it does not need to re-render.
I came up with two different solutions. The first is to clone the model on each update. In some cases this is fine, and maybe it's the functional programming way of doing things (I'm almost as new to functional programming as I am to React). But it seems like a waste to go around cloning things all the time.
The second solution is to use the forceUpdate
strategy posted at https://medium.com/crowdbotics/how-to-use-usereducer-in-react-hooks-for-performance-optimization-ecafca9e7bf5. If I wrap that thing up in a nice custom hook, I can make it pretty clean. But I know that forceUpdate is not really recommended, and I'm not comfortable enough yet with react to know if this is a reasonable place to use it.
I've got everything laid out clearly in a jsfiddle at https://jsfiddle.net/nbrustein/odjwkbvs/31/
So, what should I be doing here? Is the solution:
- Stop worrying and love the clone. It's what all the cool functional programmers are doing these days.
- Use forceUpdate. This is what it's for.
- Something else I haven't thought of yet.
Thanks in advance for any insights.
Top comments (2)
I figured out how to get it working without forceUpdate. What I did was to stop trying to bind directly to the property on the model. Instead, I set up a state variable using
useState
, and then whenever I observe a change to it, I push that change onto the model. Seems like the React way of doing things.I've updated the jsfiddle with the new strategy: jsfiddle.net/nbrustein/odjwkbvs/40/
React updates the React component tree by comparing the reference of a state (Refer to Reconciliation).
In your case,
updateProperty
updates the property of the model, not the reference ofmyModel
. Thus React thinks that there is no need to update the tree.When using
useReducer
, you would usually dispatch an action, which is a Redux way of returning a new state.And you can return a new reference
return Object.assign({}, action.model, {property: action.property});
by returning a new object from the reducer (modelReducer
).Instead of using
myModel
directly, you usemodel
returned fromuseReducer
, which gets the new value frominput.onChange
.I've forked your initial fiddle and created a working version using the code above.
jsfiddle.net/dance2die/tw8759da/21/