DEV Community

Discussion on: What is the best way to update a property on a model using React hooks

Collapse
 
dance2die profile image
Sung M. Kim • Edited

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 of myModel. Thus React thinks that there is no need to update the tree.

  const updateProperty = useReducer((myModel, newValue) => {
    myModel.property = newValue;
    return myModel;
  }, myModel)[1];

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 use model returned from useReducer, which gets the new value from input.onChange.

function modelReducer(state, action) {
    switch (action.type) {
    case 'UPDATE_PROPERTY': 
        // return a new object reference
        return Object.assign({}, action.model, {property: action.property});
        // if using ES9, which supports object spread
        // return {...action.model, property: action.property);
    default: return state;
  }
}

function DontWork() {
  const myModel = useModel()[0];
  const [model, dispatch] = useReducer(modelReducer, myModel);

  return (
    <div>
      <h1>Now works</h1>
      <input
        onChange={e => dispatch({type: 'UPDATE_PROPERTY', model, property: e.target.value})}
      /> 
      <span>{model.property}</span>
    </div>
  )
}

I've forked your initial fiddle and created a working version using the code above.

jsfiddle.net/dance2die/tw8759da/21/