问题描述
const [userInfo,setUserInfo] = useState({
author:"",user: {
name: 'rahul',email: 'rahul@gmail.com',phone: [{ primary: '8888888810' },{ alternate: '7777777716' }]
}
});
我想要 5 个输入字段 - 作者、姓名、电子邮件、主要和备用,并且只想使用一个 handleChange() 方法来更改字段。
你可以在链接上找到我写的代码 - https://stackblitz.com/edit/react-ngpx7q
在这里,我无法弄清楚如何正确更新状态。任何帮助将不胜感激。
解决方法
由于这是一个面试问题,所以我会避免使用 3rd 方库。您可以使用 switch
语句来处理不同的嵌套状态,即第二级的 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
}
};
演示
,您可以使用 lodash set 为深度嵌套的对象分配值。您需要将 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>
);
};
现在您可以使用单个 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: 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>
);
}
,
这基于您的原始数据(其中 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}]
}
};
});
}
};
,
我复制粘贴你的代码,只编辑你的 handleChange
import React,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,phone: arrPhone
}
};
});
};
const {
name,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>
);
}