【问题标题】:Meteor.logout() causing memory leak in ReactMeteor.logout() 在 React 中导致内存泄漏
【发布时间】:2019-08-05 05:56:24
【问题描述】:

当我注销我的流星应用程序时,出现内存泄漏错误。这似乎发生在大约 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>
    );
  }
}

【问题讨论】:

    标签: reactjs meteor


    【解决方案1】:

    因此,我将为您分解此内容,以了解错误是什么,遇到错误的原因以及解决方案的一些可能想法。

    您的组件LogoutButton 正在运行它已卸载(完全未渲染)但正试图触发组件内的状态更改的情况。这通常只是糟糕的状态流,通常源于执行一些需要时间的异步操作,然后在没有什么可以触发 setState 时触发 setState。

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

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

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

    我对 React-Router 知之甚少(这是我假设 &lt;Redirect /&gt; 的来源,但它看起来像 history.push 或将名为 push 的道具传递给 &lt;Redirect /&gt; 是值得考虑的事情。见this article.

    【讨论】:

      【解决方案2】:

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

      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>
          );
        }
      }
      

      【讨论】:

      • 好的,所以这不起作用。解决方法,作为一个肮脏的黑客,是在用户退出后强制应用重新加载。
      【解决方案3】:

      step1 .meteor 文件夹添加这个包: 帐户-ui 帐户-谷歌 帐户密码 账户基础 标准:帐户-ui 用户帐户:引导 // 第2步 : 文件夹:导入/启动 创建文件夹名称“accounts”添加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="/" />
        }
      })
      

      【讨论】:

      • 很高兴您提交了一些代码,但这如何解决 OP 的问题?您的代码如何防止内存泄漏?他们做错了什么?
      • 目前也在使用meteor,react。
      • 在你想注销的时候调用这个: let handleLogout = () => { AccountsTemplates.logout() }
      • 是的,可能您的问题已解决。流星包:accounts-ui accounts-google accounts-password accounts-base session@1.2.0 std:accounts-ui useraccounts:bootstrap
      • 我尽力解释。 :D
      猜你喜欢
      • 2015-07-06
      • 2014-06-07
      • 2013-11-20
      • 2011-10-28
      • 2016-01-18
      • 2012-12-13
      • 1970-01-01
      • 2011-01-08
      • 2011-02-01
      相关资源
      最近更新 更多