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
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" />
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With