Reputation: 151
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
Upvotes: 5
Views: 7270
Reputation: 26518
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)} />
/>
)
}
Upvotes: 4
Reputation: 281606
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" />
Upvotes: 8
Reputation: 4285
setUser
is a function same as setState
.. for more details check hooks
<input
value={User.name}
onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
/>
in your context:
const App = () => {
const [User, setUser] = useState({
id: 1,
name: "ed",
age: Number,
edit: false
});
return (
<div>
<input
value={User.name}
onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
/>
);
};
Upvotes: 1