从 useSelector() 编辑局部变量时,Redux 状态正在发生变化
Redux state is mutating when editing local variable from useSelector()
我正在使用 useSelector() 来获取状态,当我将一些过滤器应用于本地状态变量时,我的全局状态正在发生变化。不知道为什么。下面是代码。
const filterVacations = (employees, status) => {
if(status === 'Approved') {
employees.forEach(item => {
item.vacations = item.vacations.filter(vac => vac.approved === true);
});
}
else if(status === 'Unapproved') {
employees.forEach(item => {
item.vacations = item.vacations.filter(vac => vac.approved === false);
});
}
return employees.filter(item => item.vacations.length > 0);
}
并按如下方式调用此函数:
const Vacations = () => {
const state = useSelector((state:State) => state);
const view = state.view;
const filter = state.filter;
const employees = state.employees;
employees = filterVacations(employees, filter);
return (
<>
//some component...
</>);
}
为什么状态在这里发生变化?
这是因为当您说 const filter = state.filter;
时,您传递的不是价值,而是传递引用。
例如,假设图书馆中有一个书架,上面放着 JS 书。当你访问图书馆时,不会给你书的副本,而是给你书的位置。因此,如果您撕下书页并将其放在原处。图书管理员也可以看到撕破的页面。但是,如果您不希望发生这种情况。您需要获取这本书的副本并撕掉其中的页面,而书架上的书将保持原样。
因此,当您想复制数据并将其存储在变量中时,ES6 引入了比之前笨拙的方法更简单的方法。所以这个const filter = state.filter;
会变成这个const filter = [...state.filter]; // this makes copy of array
我发现了问题。 useSelector 将 return 嵌套对象的浅表副本,因此发生变异。解决办法是手动深拷贝。
我正在使用 useSelector() 来获取状态,当我将一些过滤器应用于本地状态变量时,我的全局状态正在发生变化。不知道为什么。下面是代码。
const filterVacations = (employees, status) => {
if(status === 'Approved') {
employees.forEach(item => {
item.vacations = item.vacations.filter(vac => vac.approved === true);
});
}
else if(status === 'Unapproved') {
employees.forEach(item => {
item.vacations = item.vacations.filter(vac => vac.approved === false);
});
}
return employees.filter(item => item.vacations.length > 0);
}
并按如下方式调用此函数:
const Vacations = () => {
const state = useSelector((state:State) => state);
const view = state.view;
const filter = state.filter;
const employees = state.employees;
employees = filterVacations(employees, filter);
return (
<>
//some component...
</>);
}
为什么状态在这里发生变化?
这是因为当您说 const filter = state.filter;
时,您传递的不是价值,而是传递引用。
例如,假设图书馆中有一个书架,上面放着 JS 书。当你访问图书馆时,不会给你书的副本,而是给你书的位置。因此,如果您撕下书页并将其放在原处。图书管理员也可以看到撕破的页面。但是,如果您不希望发生这种情况。您需要获取这本书的副本并撕掉其中的页面,而书架上的书将保持原样。
因此,当您想复制数据并将其存储在变量中时,ES6 引入了比之前笨拙的方法更简单的方法。所以这个const filter = state.filter;
会变成这个const filter = [...state.filter]; // this makes copy of array
我发现了问题。 useSelector 将 return 嵌套对象的浅表副本,因此发生变异。解决办法是手动深拷贝。