[英]React clean up function when setting context via hook api
我有一个通过反应挂钩设置的上下文。 初始状态如下:
const initialState = {
allTasks: [],
tasksToAuth: [],
pendingTasks: [],
completedTasks: [],
users: [],
headers: headers,
categories: categories
};
尝试通过api设置前五个属性时,会导致错误“无法在已卸载的组件上执行React状态更新。这是空操作,但表明您的应用程序中存在内存泄漏。要修复,取消useEffect清理功能中的所有订阅和异步任务。”
我的api代码位于useEffect挂钩中。
React.useEffect(() => {
async function getItems() {
try {
await actions.setAllTasks();
await actions.setUsers();
await actions.setUserPendingTasks();
await actions.setTasksToAuth();
await actions.setUserCompletedTasks();
} catch (e) {
alert("Error hit ", e);
console.log(e);
}
}
getItems();
}, [actions]);
我的动作和中间件/减速器如下:
Actions.js
setAllTasks: tasks => dispatch({ type: "admin.set.all.tasks", payload: tasks }),
setTasksToAuth: tasks => dispatch({ type: "admin.set.submitted", payload: tasks }),
setUserPendingTasks: tasks => dispatch({ type: "admin.set.pending", payload: tasks }),
setUserCompletedTasks: tasks => dispatch({ type: "admin.set.completed", payload: tasks }),
setUsers: tasks => dispatch({ type: "admin.set.users", payload: tasks }),
Middleware.js
switch (action.type) {
case "admin.set.all.tasks":
axios
.get("http://localhost:3001/api/admin/tasks")
.then(res => {
console.log(res);
dispatch({ type: action.type, payload: res.data.data });
})
.catch(e => console.log(e));
break;
case "admin.set.pending":
axios
.get("http://localhost:3001/api/admin/tasks/pending")
.then(res => {
console.log(res.data.data);
dispatch({ type: action.type, payload: res.data.data });
})
.catch(e => console.log(e));
break;
case "admin.set.submitted":
axios
.get("http://localhost:3001/api/admin/tasks/submitted")
.then(res => {
console.log(res.data.data);
dispatch({ type: action.type, payload: res.data.data });
})
.catch(e => console.log(e));
break;
case "admin.set.completed":
axios
.get("http://localhost:3001/api/admin/tasks/completed")
.then(res => {
console.log(res.data.data);
dispatch({ type: action.type, payload: res.data.data });
})
.catch(e => console.log(e));
break;
case "admin.set.users":
axios
.get("http://localhost:3001/api/admin/users/")
.then(res => {
console.log(res);
dispatch({ type: action.type, payload: res.data.data });
})
.catch(e => console.log(e));
break;
最后,reducer.js
case "admin.set.all.tasks":
console.log("admin.set.all.tasks");
return { ...state, allTasks: action.payload };
case "admin.set.pending":
console.log("admin.set.pending");
return mapPendingTasks(state, action.payload);
case "admin.set.submitted":
console.log("admin.set.submitted");
return mapSubmittedTasks(state, action.payload);
case "admin.set.completed":
console.log("admin.set.completed");
return mapCompletedTasks(state, action.payload);
case "admin.set.users":
console.log("admin.set.users");
return { ...state, users: action.payload };
似乎错误发生在这里-“ TypeError:无法设置未定义或空引用的属性'uin'”
据我所知,首先未正确设置allTasks的状态才能在下面首先创建任务对象?
reducer.js中返回的函数的示例是:
function mapCompletedTasks(state, payload) {
let tasks = [];
payload.forEach(element => {
let task = state.allTasks.filter(e => e.id === element.task_id)[0];
task.uin = element.uin;
task.status = element.status;
task.due_by = element.due_by;
task.submitted_on = element.submitted_on;
task.completed_on = element.completed_on;
tasks.push(task);
});
return { ...state, completedTasks: tasks };
}
我怎么解决这个问题? 我已经在React useEffect中看到过清理
return () => cleanup();
但是我不确定如何执行。 谢谢
编辑:更好地格式化代码编辑2:添加了看到的另一个错误
如所评论; 您可以使用useIsMounted ,尽管我不会用yarn / npm安装它,而是将其添加到lib或其他代码中:
export default function CountersContainer() {
const [val, setVal] = useState([1]);
useEffect(() => {
//cause all items to unmount in half a second
setTimeout(() => setVal([]), 500);
});
return (
<div>
{val.map(val => (
<Item val={val} key={val} />
))}
</div>
);
}
//item will be unmounted in half a second
const Item = ({ val }) => {
const isMounted = useIsMounted();
const set = useState()[1];
useEffect(() => {
//trying to do a set state after Item is unmounted
setTimeout(() => {
//luckily it'll check if it's mounted
if (isMounted.current) {
set(22);
}
}, 700);
}, [isMounted, set]);
return <div>{val}</div>;
};
const useIsMounted = () => {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => (isMounted.current = false);
}, []);
return isMounted;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.