使用状态/使用效果反应传播运算符的错误



我遇到了一个问题,我正在使用扩展运算符设置状态,但useEffect中的函数调用只会将从 API 拉取的最后一个值设置为状态。

// get all events to display on load
const getEvents = () => {
console.log(props.id);
axios.get(API.EVENTS.ROOT + props.id).then(
res => {
const data = res.data;
setEvent(data);
console.log(data);
// event start and end dates
setStart(new Date(data.start));
setEnd(new Date(data.finish));
// breakout dates
for (let i = 0; i < data.breakouts.length; i++) {
console.log(data.breakouts[i].start);
data.breakouts[i].start = new Date(data.breakouts[i].start);
data.breakouts[i].end = new Date(data.breakouts[i].end);
console.log(data.breakouts[i].name, "test" + data.breakouts[i].start);
// set date picker initial value 
setFields({
...fields,
[data.breakouts[i].name]: data.breakouts[i].start
})
console.log(fields);
}
setBreakoutRow(data.breakouts);
console.log(breakoutRow);
}
).catch(err => {
console.log(err);
})
}
// get events on load
useEffect(() => {
console.log(props);
getEvents();
}, []);

我添加字段状态变量或getEvents函数作为依赖项,它确实更新了所有值的字段state,但它会导致无限的死亡循环。这给了我除最后一个之外的所有映射行中的空白日期。

另一个需要注意的事项是,在页面加载后,可以通过函数调用更新fields对象没有问题,如下所示:

const handleDateChange = (dateName, dateValue) => {
console.log(dateName, dateValue);
setFields({
...fields,
[dateName]: dateValue
})
console.log(fields);
}

这让我相信我的useEffect钩子有问题,但我不确定它出了什么问题。

原因是您如何访问以前的值以添加新元素:

for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
setFields({
...fields,
[data.breakouts[i].name]: data.breakouts[i].start
})
}

由于fields只会在下次渲染时更新,因此您将单个元素(但每个循环都是不同的元素(添加到数组中。

没有钩子/反应也是如此:

const start = [];
for(let i = 0; i< 5; i++) console.log([...start, i]);

这永远不会输出[0,1,2,3,4].

你能做什么。

选项 1.在术语变量中收集数据:

const temp = {};
for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
data.breakouts[i].end = new Date(data.breakouts[i].end);
temp[data.breakouts[i].name] = data.breakouts[i].start
}
setFields({
...fields,
...temp
});

选项 2.使用功能版本的二传器作为累加器:

for (let i = 0; i < data.breakouts.length; i++) {
data.breakouts[i].start = new Date(data.breakouts[i].start);
setFields(({fields: prevFields}) => ({
...prevFields,
[data.breakouts[i].name]: data.breakouts[i].start
}))
}

我更喜欢第一个选项,原因有两个:

  1. 最好最终将数据转换移近调用点,这样而不是axios.get您需要一些API.getMeaningfullThings返回结构;因此更容易重构
  2. 也许稍微多一点的代码可以更好地显示正在发生的事情(这只是一个转换,而不是过滤或任何特定于 React 的东西(

如果我理解正确,您对第一个例子中的setState有问题。原因是你在循环内调用setState,并且你试图传播旧状态,但是在循环完成之前状态没有被设置,所以你必须在循环内累积你想要放入状态的所有内容,并在最后设置它。

相关内容

  • 没有找到相关文章

最新更新