我正在使用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...
</>);
}
为什么状态在这里突变?
答案 0 :(得分:1)
这是因为说const filter = state.filter;
不是传递值,而是传递引用。
例如,考虑一个在图书馆中最上面有JS书的书架。当您访问Libraria时,不会给您书的副本,而是书的位置。因此,如果您撕开该书的页面并将其放在同一位置。图书馆员也可以看到残缺的页面。但是,如果您不希望这种情况发生。您需要获取书的副本并从书中撕掉页面,而书架上的书将保持原样。
因此,当您想复制数据并将其存储在变量中时,ES6引入了比以前笨拙的方式更简单的方法。所以这个const filter = state.filter;
将成为此const filter = [...state.filter]; // this makes copy of array
答案 1 :(得分:1)
我发现了问题。 useSelector将返回嵌套对象的浅表副本,从而进行突变。解决方案是手动进行深度复制。