怎么还记得一个React Hooks组件是卸载的,所以可以避免状态改变?

时间:2019-05-27 06:27:05

标签: reactjs react-hooks

使用基于旧类的React.js代码,我可以这样做,以记住已卸载组件:

  componentWillUnmount: function() {
    this.isGone = true;
  },

  loadUsers: function() {
    Server.loadUsers(..., (response) => {
      if (this.isGone) return;
      ...
    });
  }

使用基于钩子的组件如何做同样的事情?

这是一个示例挂钩函数组件,我不确定如何记住它已被卸载,因此可以在调用任何return之前先setSomeState

export const GroupMembers = React.createFactory(function(props) {

  const [membersOrNull, setMembers] = React.useState(null);
  let isGone = false;  // ? (se [222] below

  React.useEffect(() => {
    Server.listGroupMembers(someGroupId, (response) => {
     if (/* is unmounted ?? */) return;
     setMembers(response.members);
    });
    return () => { /* how remember is unmounted?
                      would isGone = true; work? */ };
  }, []);

  ...

  return ..., Button({ title: "Remove all members", onClick: () => {
    Server.removeAllMembers(someGroupId, () => {
     if (/* is unmounted ?? */) return;
     setMembers([]);
    });
  }});

我想我不能使用const [isGone, setGone] = useState(false),因为卸载后我不应该尝试访问状态(读isGone)。而且如果我 [222] 在函数内部添加本地let isGone = false,在我看来,在函数内部创建的各种回调将引用此局部变量的不同“实例”,具体取决于在哪个不同的GroupMembers(..)调用中创建了不同的回调?还是我弄错了,这行得通吗? —也许我可以使用本地let isGone = false创建一个外部包装函数,但是,这添加了另一个包装函数和缩进:-/

2 个答案:

答案 0 :(得分:1)

只使用通过闭包访问的局部变量

React.useEffect(() => {
  let isActual = true;
  Server.listGroupMembers(someGroupId, (response) => {
     if (!isActual) return;
     setMembers(response.members);
  });
  return () => {isActual = false;};
}, []);

在这种情况下,仅在卸载时会更新标志。但在一般情况下(对于useEffect具有一些非空的依赖关系)也将使用它。因此,在进行顺序渲染的情况下,可以确保您从未处理过较早的请求。

PS最普遍的方式是在可能的情况下取消请求。

答案 1 :(得分:1)

由于您也使用了isGone方法之外的useEffect标志,因此可以使用useRef来存储变量,如

export const GroupMembers = React.createFactory(function(props) {

  const [membersOrNull, setMembers] = React.useState(null);
  const isGone = useRef(false);  // ? (se [222] below

  React.useEffect(() => {
    Server.listGroupMembers(someGroupId, (response) => {
     if (isGone.current) return;
     setMembers(response.members);
    });
    return () => { 
       isGone.current = true;
    };
  }, []);

  ...

  return ..., Button({ title: "Remove all members", onClick: () => {
    Server.removeAllMembers(someGroupId, () => {
     if (isGone.current) return;
     setMembers([]);
    });
  }});
  

PS:处理此类问题的更好方法是在出现以下情况时取消请求   您要离开页面,而不是仅等待响应   忽略它。