繁体   English   中英

通过挂钩API设置上下文时反应清理功能

[英]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'”

据我所知,首先未正确设置allTask​​s的状态才能在下面首先创建任务对象?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM