Json 反应:在设置状态的事件中传递一个道具
我正在使用一个嵌套状态对象,我一直在使用onChange函数更新它,如下所示:Json 反应:在设置状态的事件中传递一个道具,json,reactjs,events,nested,state,Json,Reactjs,Events,Nested,State,我正在使用一个嵌套状态对象,我一直在使用onChange函数更新它,如下所示: const [someState, setSomeState] = useState({ customer: [ { name: "Bob", address: "1234 Main Street", email: "bob@mail.com", phone: [ { mobile: "
const [someState, setSomeState] = useState({
customer: [
{
name: "Bob",
address: "1234 Main Street",
email: "bob@mail.com",
phone: [
{
mobile: "555-5555",
home: "555-5555"
}
]
}
]
});
const updateSomeStatePhone = e => {
e.persist();
setSomeState(prevState => {
prevState.customer[0].phone[0].mobile = e.target.value;
return {
...prevState
};
});
};
<p>Update Mobile Number<p>
<select
value={someState.customer[0].phone[0].mobile}
onChange={updateSomeStatePhone}
>
<option value="123-4567">"123-4567"</option>
</select>
但是函数从不识别我从函数传入的“道具”。我相信一定有一个简单的方法可以做到这一点。任何帮助都将不胜感激。请使用lodash的助手
顺便说一句,在您现有的
updateStatePhone
中,您正在修改prevState
对象,该对象应该是不可变的。它必须是单个useState
钩子吗?我建议使用useReducer
或使用多个useState
挂钩将其简化一点
多个useState
hook
useReducer
是一个更好的选择。互联网上到处都是例子
为什么不应该使用useState
传递对象,是因为它的行为不像setState
。基础对象引用是相同的。因此,react永远不会触发状态更改。如果要对对象使用相同的useState
。您可能需要实现自己的版本来扩展它(下面的例子),或者您可以直接使用hook来实现相同的功能
下面是一个使用useState
的示例,让您注意到每次更改时的状态更新
const [form, setValues] = useState({
username: "",
password: ""
});
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.value
});
};
注意那里的…表单
。您可以在每次更新中这样做,也可以使用自己的实用程序或我提到的useReducer
现在谈到您的代码,还有其他问题
手机
作为一个数组,可以是一个对象。或者更好的是,单独的属性也可以。没有害处客户
作为一个数组,则必须循环浏览记录。不仅仅是通过硬编码来更新索引。如果只有一个客户,最好不要保留阵列,而只保留一个对象。假设它是一个客户阵列,并且您在其中循环,下面介绍如何更新mobile
[e.target.name]
非常感谢您的回复。我将调查用户教育者。不幸的是,我无法更改正在使用的状态对象的结构。否则,我肯定看到了重组状态和使用你建议的方法的价值。我没有说你是强制使用它的。我从useState和use Reducer的角度解释了使用what和what NOT的原因。另外,我指出了不使用循环来更新应该更新的位置的方法。如果是一次性更新,则为另一种情况。感谢您至少对我的回答表示感谢。非常感谢您的回复。问题是。与@ckedar推荐的lodash相比,使用还原剂是否有任何优势?这似乎是访问嵌套项的最干净的方式。嗯,他似乎删除了他的评论。无所谓。我还注意到reducer函数是在组件外部声明的。如果我将此组件与许多其他具有减速器的类似组件一起导入,这会导致问题吗?一个优点是,使用减速器,您可以更灵活地精确控制状态。您还可以为每个操作/字段执行独特的操作,并添加新操作(例如:清除或重置)。而且它不需要添加另一个依赖项(因为它是香草反应)。如果我需要以上面列出的原始状态访问第二个“customer”数组对象来设置名称(state.customer[1].name),该怎么办?我似乎找不到正确的语法。我得到了以下内容:``case“SET_CUST1_NAME”:返回{…state,customer:[{…state.customer[1],NAME:value}]```使用它比使用减速机有什么好处吗?@yummylumpkins-Less样板代码。如果向客户添加新属性,则不需要更改更新代码。我们可以使用u.set编写reducer来消除样板代码,但一般来说,在处理更复杂的状态时,我将使用reducer,该状态的组件之间存在交互/相互依赖关系。
prevState.prop = e.target.value;
prevState.(prop) = e.target.value;
${prevState} + '.' + ${prop} = e.target.value; // Dumb, I know
const updateSomeState = (e, prop) => {
e.persist();
setSomeState(prevState => {
let customers = [...prevState.customers] // make a copy of array
let customer = {...customers[0]} // make a copy of customer object
_.set(customer, prop, e.target.value)
customers[0] = customer;
return {
...prevState, customers
};
});
};
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const [name, setName] = React.useState("");
const [address, setAddress] = React.useState("");
const [email, setEmail] = React.useState("");
const [mobile, setMobile] = React.useState("");
const [home, setHome] = React.useState("");
const getResult = () => ({
customer: [
{
name,
address,
email,
phone: [
{
mobile,
home
}
]
}
]
});
// Do whatever you need to do with this
console.log(getResult());
return (
<>
<input
value={name}
placeholder="name"
onChange={e => setName(e.target.value)}
/>
<br />
<input
value={address}
placeholder="address"
onChange={e => setAddress(e.target.value)}
/>
<br />
<input
value={email}
placeholder="email"
onChange={e => setEmail(e.target.value)}
/>
<br />
<input
value={mobile}
placeholder="mobile"
onChange={e => setMobile(e.target.value)}
/>
<br />
<input
value={home}
placeholder="home"
onChange={e => setHome(e.target.value)}
/>
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
const [form, setValues] = useState({
username: "",
password: ""
});
const updateField = e => {
setValues({
...form,
[e.target.name]: e.target.value
});
};
const updatedCustomers = state.customers.map(item => {
const { phone } = item;
return { ...item, phone: { mobile: e.target.value }};
// returns newCustomer object with updated mobile property
});
// Then go ahead and call `setSomeState ` from `useState`
setSomeState(...someState, { customer: updatedCustomers });// newState in your case is
return { ...item, phone: { [e.target.name]: e.target.value }};