替换状态数组后使用 useEffect 更新子组件的正确方法
Correct way to use useEffect to update Child Component after replacing state array
我有一个父组件 "Checkout",我在其中调用我的 api 获取活动门票并将数据保存到状态。我有一个简单的功能,它获取现有的票证信息并将一个信息添加到用户选择的票证中。
结帐组件
const handleTicketAdd = (e) => {
// create new ticket array
const newTickets = tickets;
//
newTickets[e.target.id].count++;
console.log(newTickets);
setTickets(newTickets);
console.log(tickets);
}
此函数作为 prop 传递给子组件 "Tickets" 并在映射行中调用。
该函数工作正常,正在更新控制台中的计数状态,但子组件没有重新渲染,屏幕上的值仍保持初始值。
我一直在研究并发现 componentWillReceiveProps 已被 useEffect 挂钩所取代。我一直试图让它在我的子组件中工作,但没有成功:
门票组件
useEffect(()=>{
console.log("Tickets Changed", props.tickets);
}, [props.tickets]);
props.tickets 更改时日志不会触发,所以我知道我没有正确处理这个问题。有人能给我指出正确的方向吗?
更新
根据下面的反馈,我修改了我的代码,它几乎完成了。问题是它在数组中添加了一个新字段,其中包含对象的计数值,而不是仅仅更新对象的计数字段。
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1])
)
如果我尝试弹出最后一个值之类的操作,我会在数组中添加更多新字段。我将如何实现删除正在生成的附加字段。以下无效:
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.pop()),
)
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.slice(-1)[0),
)
你不应该在更新时改变状态,相反你需要克隆和更新状态
const handleTicketAdd = (e) => {
const id = e.target.id;
setTickets(prevTickets => ([
...prevTickets.slice(0, id),
{
...prevTickets[id],
count: prevTickets[id].count + 1
}
...prevTickets.slice(id + 1);
]));
}
好吧,看起来编辑数组状态的方法应该使用映射函数或使用先前状态的循环来完成。我能够根据 Shubham 的反馈来解决这个问题。
// update count based on previous state
setTickets(prevTickets => (prevTickets.map((ticket, index) => {
console.log(index, e.target.id);
// if mapped object's id equals the arrays index, it's the value to edit
if (e.target.id == index) {
console.log(index);
const count = ticket.count + 1;
// return object with updated count values
return { ...ticket, count }
}
return ticket;
})
))
这使我可以编辑数组中我想要的对象值,而无需任何其他字段或值。
我有一个父组件 "Checkout",我在其中调用我的 api 获取活动门票并将数据保存到状态。我有一个简单的功能,它获取现有的票证信息并将一个信息添加到用户选择的票证中。
结帐组件
const handleTicketAdd = (e) => {
// create new ticket array
const newTickets = tickets;
//
newTickets[e.target.id].count++;
console.log(newTickets);
setTickets(newTickets);
console.log(tickets);
}
此函数作为 prop 传递给子组件 "Tickets" 并在映射行中调用。
该函数工作正常,正在更新控制台中的计数状态,但子组件没有重新渲染,屏幕上的值仍保持初始值。
我一直在研究并发现 componentWillReceiveProps 已被 useEffect 挂钩所取代。我一直试图让它在我的子组件中工作,但没有成功:
门票组件
useEffect(()=>{
console.log("Tickets Changed", props.tickets);
}, [props.tickets]);
props.tickets 更改时日志不会触发,所以我知道我没有正确处理这个问题。有人能给我指出正确的方向吗?
更新
根据下面的反馈,我修改了我的代码,它几乎完成了。问题是它在数组中添加了一个新字段,其中包含对象的计数值,而不是仅仅更新对象的计数字段。
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1])
)
如果我尝试弹出最后一个值之类的操作,我会在数组中添加更多新字段。我将如何实现删除正在生成的附加字段。以下无效:
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.pop()),
)
setTickets(prevTickets => ([...prevTickets, prevTickets[e.target.id].count = prevTickets[e.target.id].count + 1], prevTickets.slice(-1)[0),
)
你不应该在更新时改变状态,相反你需要克隆和更新状态
const handleTicketAdd = (e) => {
const id = e.target.id;
setTickets(prevTickets => ([
...prevTickets.slice(0, id),
{
...prevTickets[id],
count: prevTickets[id].count + 1
}
...prevTickets.slice(id + 1);
]));
}
好吧,看起来编辑数组状态的方法应该使用映射函数或使用先前状态的循环来完成。我能够根据 Shubham 的反馈来解决这个问题。
// update count based on previous state
setTickets(prevTickets => (prevTickets.map((ticket, index) => {
console.log(index, e.target.id);
// if mapped object's id equals the arrays index, it's the value to edit
if (e.target.id == index) {
console.log(index);
const count = ticket.count + 1;
// return object with updated count values
return { ...ticket, count }
}
return ticket;
})
))
这使我可以编辑数组中我想要的对象值,而无需任何其他字段或值。