[英]React - using nested objects as state with hooks to fill form data
I have a nested object as state like below -我有一个嵌套的 object 作为 state 如下所示 -
const [userInfo, setUserInfo] = useState({
author:"",
user: {
name: 'rahul',
email: 'rahul@gmail.com',
phone: [{ primary: '8888888810' }, { alternate: '7777777716' }]
}
});
I want to have 5 input fields - author, name, email, primary, and alternate and want to use only one handleChange() method to change the fields .我想要 5 个输入字段 - 作者、姓名、email、主要和备用字段,并且只想使用一个 handleChange() 方法来更改字段。
You can find the code I wrote on the link - https://stackblitz.com/edit/react-ngpx7q您可以在链接上找到我写的代码 - https://stackblitz.com/edit/react-ngpx7q
Here, I am not able to figure out how to update the state correctly.在这里,我无法弄清楚如何正确更新 state。 Any help would be greatly appreciated.
任何帮助将不胜感激。
Since this was an interview question then I'd avoid 3rd-party libraries.由于这是一个面试问题,所以我会避免使用 3rd-party 库。 You can use a
switch
statement to handle the differently nested state, namely the name
and email
in the second level and primary
and alternate
in the third level.您可以使用
switch
语句来处理不同嵌套的state,即第二层的name
和email
和第三层的primary
和alternate
。
const handleChange = (e) => {
const { name, value } = e.target;
switch (name) {
case "name":
case "email":
setUserInfo((userInfo) => ({
user: {
...userInfo.user,
[name]: value
}
}));
break;
case "primary":
case "alternate":
setUserInfo((userInfo) => ({
user: {
...userInfo.user,
phone: userInfo.user.phone.map((el) =>
el.hasOwnProperty(name)
? {
[name]: value
}
: el
)
}
}));
break;
default:
// ignore
}
};
you can use lodash set to assign the value for the deeply nested object.您可以使用 lodash set为深度嵌套的 object 分配值。 You need to pass the
path
to the name
prop of your input.您需要将
path
传递给输入的name
道具。
import set from 'lodash/set'
const App = () => {
const [userInfo, setUserInfo] = useState({
author:"",
user: {
name: 'rahul',
email: 'rahul@gmail.com',
phone: [{ primary: '8888888810' }, { alternate: '7777777716' }]
}
});
const handleChange = (e) => {
// clone the state
const userInfoCopy = JSON.parse(JSON.stringify(userInfo));
set(userInfoCopy, e.target.name, e.target.value)
setUserInfo(userInfoCopy)
}
console.log(userInfo)
return (
<div>
<input
name="user.name"
onChange={handleChange}
/>
<input
name="user.phone.[0].primary"
onChange={handleChange}
/>
</div>
);
};
Now you can use a single handleChange
method for updating all your keys in the state.现在您可以使用单个
handleChange
方法来更新 state 中的所有密钥。
Instead of treating phone as object of array, which i don't think is a good idea, treat it as single object with primary and alternate as key value pairs与其将电话视为数组的 object(我认为这不是一个好主意),不如将其视为单个 object,将主要和备用作为键值对
import React, { useState } from 'react';
import './style.css';
export default function App() {
const [userInfo, setUserInfo] = useState({
user: {
name: 'ravi',
email: 'ravi@gmail.com',
phone: {
primary: 345345345345,
alternate: 234234234234
}
}
});
const handleChange = e => {
console.log(e.target.name);
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[e.target.name]: e.target.value,
phone: {
...prevState.user.phone,
...{ [e.target.name]: e.target.value }
}
}
};
});
};
const {
name,
email,
phone: { primary, alternate }
} = userInfo.user;
console.log(userInfo);
return (
<div className="App">
Name: <input name="name" value={name} onChange={e => handleChange(e)} />
<br />
Email:{' '}
<input name="email" value={email} onChange={e => handleChange(e)} />
<br />
Primary:{' '}
<input name="primary" value={primary} onChange={e => handleChange(e)} />
<br />
Alternate:{' '}
<input
name="alternate"
value={alternate}
onChange={e => handleChange(e)}
/>
<br />
</div>
);
}
This works based on your original data (where phone is an array of objects):这基于您的原始数据(其中 phone 是一个对象数组):
const handleChange = e => {
let name = e.target.name;
if (['name', 'email'].includes(name)) {
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[name]: e.target.value,
}
};
});
} else {
setUserInfo(prevState => {
return {
user: {
...prevState.user,
phone: name === 'primary' ?
[prevState.user.phone.find(e => Object.keys(e).includes('alternate')), {[name]: e.target.value}] :
[prevState.user.phone.find(e => Object.keys(e).includes('primary')), {[name]: e.target.value}]
}
};
});
}
};
I copy paste your code and only edit your handleChange我复制粘贴你的代码,只编辑你的 handleChange
import React, { useState } from 'react';
import './style.css';
export default function App() {
const [userInfo, setUserInfo] = useState({
user: {
name: 'ravi',
email: 'ravi@gmail.com',
phone: [{ primary: '9999999990' }, { alternate: '9999998880' }]
}
});
const handleChange = e => {
console.log(e.target.name);
let arrPhone = userInfo.user.phone;
(e.target.name == 'primary' || e.target.name == 'alternate' )
&& arrPhone.map(x => (x.hasOwnProperty(e.target.name)) && (x[e.target.name] = e.target.value))
console.log(arrPhone)
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[e.target.name]: e.target.value,
phone: arrPhone
}
};
});
};
const {
name,
email,
phone: [{ primary }, { alternate }]
} = userInfo.user;
console.log(userInfo);
return (
<div className="App">
Name: <input name="name" value={name} onChange={handleChange} />
<br />
Email: <input name="email" value={email} onChange={handleChange} />
<br />
Primary: <input name="primary" value={primary} onChange={handleChange} />
<br />
Alternate:{' '}
<input name="alternate" value={alternate} onChange={handleChange} />
<br />
</div>
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.