Meteor.logout() 在 React 中导致内存泄漏

Meteor.logout() causing memory leak in React

当我注销我的 meteor 应用程序时,出现内存泄漏错误。它似乎有大约 50% 的时间发生,我不知道我在这里做错了什么。谁能解释一下我的方法有什么问题。

错误信息

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,取消 componentWillUnmount 方法中的所有订阅和异步任务。

应用详情

Metoer、React、React-Router V4

路径:LogoutButton.jsx

class LogoutButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      logoutRedirect: false
    };

    this.handleLogout = this.handleLogout.bind(this);
  }

  handleLogout = e => {
    e.preventDefault();

    Meteor.logout(err => {
      if (err) {
        console.log('err', err);
      } else {
        this.setState({ logoutRedirect: true });
      }
    });
  };

  render() {
    const logoutRedirect = this.state;

    if (logoutRedirect.logoutRedirect) {
      return <Redirect to="/" />;
    }

    return (
      <button
        type="button"
        className="btn btn-link dropdown-item text-dark"
        onClick={this.handleLogout}
      >
        <FontAwesomeIcon icon={faSignOutAlt} className="mr-2 text-dark" />
        Logout
      </button>
    );
  }
}

如果有人能对此提供更多说明,我将不胜感激。问题似乎出在我处理经过身份验证的路由的方式上。我已经用下面的代码解决了这个错误,但是,我不太确定为什么会这样,所以我无法给出解释。解决方案是更改操作顺序。首先,更新状态以重定向路由,然后注销用户。

class LogoutButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      logoutRedirect: false
    };

    this.handleLogout = this.handleLogout.bind(this);
  }

  componentWillUnmount() {
    document.removeEventListener('click', this.handleLogout);
  }

  handleLogout = e => {
    e.preventDefault();

    this.setState({ logoutRedirect: true });
    Meteor.logout(err => {
      if (err) {
        console.log('err', err);
      }
    });
  };

  render() {
    const logoutRedirect = this.state;

    if (logoutRedirect.logoutRedirect) {
      return <Redirect to="/" />;
    }

    return (
      <button
        type="button"
        className="btn btn-link dropdown-item text-dark"
        onClick={this.handleLogout}
      >
        <FontAwesomeIcon icon={faSignOutAlt} className="mr-2 text-dark" />
        Logout
      </button>
    );
  }
}

step1.流星 文件夹添加这个包: 账户-ui 账户-google 帐户密码 账户基础 std:accounts-ui useraccounts:bootstrap // 第2步 : 文件夹:imports/startup 创建文件夹名称 "accounts" 添加帐户-config.js 并粘贴代码。 将 FlowRouter.go('/account/sign-in') 更改为 第 3 步:为您的按钮添加功能。粘贴此 let handleLogout = () => { AccountsTemplates.logout() }

const LogoutButton = () => {
   
  let handleLogout = event => {
    event.preventDefault()
    AccountsTemplates.logout()
  }

  return (
    <button
      type="button"
      className="btn btn-link dropdown-item text-dark"
      onClick={handleLogout}
    >
      <FontAwesomeIcon icon={faSignOutAlt} className="mr-2 text-dark" />
      Logout
    </button>
  )
}

注意:我使用的是帐户基础。

// Configure Accounts Templates default
AccountsTemplates.configure({
  enablePasswordChange: true,
  sendVerificationEmail: true,
  enforceEmailVerification: true,
  showForgotPasswordLink: true,
  negativeValidation: true,
  positiveValidation: true,
  negativeFeedback: true,
  positiveFeedback: true,
  // Proceed to main page as you log out..
  onLogoutHook: () => {
    <Redirect to="/" />
  }
})

所以我会为您分解一下,以了解错误是什么,您为什么 运行 陷入其中以及一些可能的解决方案。

您的组件 LogoutButton 运行 处于卸载(完全未呈现)但试图触发组件内状态更改的场景中。这通常只是糟糕的状态流,通常源于执行一些需要时间执行的异步操作,然后在没有任何东西可以触发 setState 时触发 setState。

看看你的代码,听起来你想做的是这样的:

  1. 你有一个 <LogoutButton /> 渲染到屏幕上,当 用户点击它,他们应该被重定向。
  2. 当用户单击该按钮时,它会触发 handleLogout,它会显式调用 Meteor.logout(我假设这是正式将用户从会话中注销的原因),然后继续调用 setState.

很可能,Meteor.logout 在这里有一些副作用,因此您的 LogoutButton 不再安装或渲染。当您的组件到达需要调用 setState 的步骤时,您的组件已卸载(可能某些父组件已决定不再显示它,等等)。

我对 React-Router 了解不够(这是我假设 <Redirect /> 来自但它看起来像 history.push 或将一个名为 push 的道具传递给 <Redirect /> 是值得考虑的东西。参见 this article