Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React state hook with an object

const App = () => {
  const [User, setUser] = useState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });
  return (
    <div>
      <input value={User.name} onChange={e => setUser.name(e.target.value)} />
    </div>
  );
};

I am working with react hooks. I set the initial state to an object. I try changing the value with react hooks but this gives an error TypeError: setUser.name is not a function

like image 264
Navish Avatar asked Dec 06 '22 09:12

Navish


2 Answers

setUser is a function which you use to update the state and since it just replaces the state you need to merge your previous state value too. Also event is cleared in callback so you need to get the value before using the callback of setUser. Its better to write a handler function for this. Also you can write a generic function to handle setting all values

const App = () => {
      const [User, setUser] = React.useState({
        id: 1,
        name: "ed",
        age: Number,
        edit: false
      }); 
      const handleChange = (e) => {
         const {value, name} = e.target;
         setUser(prev => ({...prev, [name]: val}))
      }
      return (
        <div>
          <input value={User.name} onChange={handleChange} />
        </div>
      );
    };
    ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app" />
like image 74
Shubham Khatri Avatar answered Dec 23 '22 05:12

Shubham Khatri


Lets look at the value of User and setUser

const [User, setUser] = useState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });

React.useState returns a value and a setter to that value. setUser is a function. So while User.name is a string with the initial value of "ed" setUser.name doesn't exist. The error TypeError: setUser.name is not a function is the result of trying to pass an undefined value an argument. One way of solving this is as Murtaza Hussain and other answers suggest:

  <input 
    value={User.name}
    onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
  />

As an alternative you can use a custom useObjState hook, which provides a rather simple API.

UseObjState hook

const useObjState = initialObj => {
  const [obj, setObj] = React.useState(initialObj);
  const setObjHelper = useMemo( () => { // the value of setObjHelper is permanent, so even if it is passed to a child component, it shouldn't require extra component updates
    const helper = {}
    Object.keys(initialObj).forEach(key => {
      helper[key] = newVal => setObj({ ...obj, [key]: newVal });
    });
    return helper
  }, [])
  return [obj, setObjHelper];
};

It provides a much easier/cleaner way to update the value of the name property.

function App() {
  const [user, setUser] = useObjState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });

  return (
    <input 
      value={user.name} 
      onChange={e => setUser.name(e.target.value)} />
    />
  )
}

Demo

like image 22
Ben Carp Avatar answered Dec 23 '22 05:12

Ben Carp