在componentWillMount中调用函数内部导致无法读取未定义

时间:2017-09-08 17:07:02

标签: javascript reactjs react-redux

React和ES6约定的新手。我试图在componentWillMount()内的函数内调用一个动作。这导致Uncaught TypeError: Cannot read property 'signoutUser' of undefined。不太确定如何解决它,尝试绑定this,这确实解决了问题。

这是我当前形式的代码:

// left_site.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { signoutUser } from '../actions/authentication';

export default function(ComposedComponent) {
    class LeftSite extends Component {

        constructor(props, context) {
            super(props, context);
        }

        componentWillMount() {

            var timerLeft = setInterval(timer, 1000);

            function timer() {

                if ((sessionStorage.getItem('timer') > 0) && 
                    (new Date().getTime() - sessionStorage.getItem('timer') > 5000)) {
                    this.props.signoutUser();
                } else {
                    sessionStorage.setItem('timer', new Date().getTime());
                }
            }
        }

        render() {
            return <ComposedComponent {...this.props} />
        }
    }

    return connect( null, { signoutUser })(LeftSite);
}

为了解释发生了什么,公司希望用户在从域上的任何受保护路由导航到另一个域时自动注销。一个想法是创建一个“心跳”,只要用户位于域上的受保护路由上,就会将时间提交到sessionStorage每秒。这个想法是如果导航到另一个域,然后尝试回来,如果最后存储时间和当前时间的差异大于5000毫秒,它将自动注销。

可能有更好的方法可以做到这一点,但我想不出1)没有违反隐私或2)不会通过刷新触发注销,例如unbind

left_site.js是一个HOC - 如果有人试图在没有身份验证的情况下尝试访问受保护的路由,我也有required_login.js HOC重新路由到登录页面 - 所以我的受保护路由被包装在{ {1}}。

component={LeftSite(RequireAuth(Home))}运行正常,但是当条件评估为LeftSite并且它尝试触发true时,错误就会出现。

2 个答案:

答案 0 :(得分:1)

函数timer未绑定到类。当以固定间隔执行时,执行上下文会发生变化。您必须在使用前绑定该函数。还要确保在适当的时间或组件卸载时清除间隔。我建议你这样写

 timer = () => {
   if ((sessionStorage.getItem('timer') > 0) && 
        (new Date().getTime() - sessionStorage.getItem('timer') > 5000)) {
          this.props.signoutUser();
   } else {
      sessionStorage.setItem('timer', new Date().getTime());
   }
}

 componentWillMount() {
   this.timerLeft = setInterval(this.timer, 1000)
 }

 componentWillUnmount() {
   clearInterval(this.timerLeft);
 }

答案 1 :(得分:1)

您需要将this绑定到计时器功能。更简单和推荐的方法是为您的计时器定义一个箭头函数,如下所示:

export default class MyComponent extends React.Component {
  componentWillMount() {
    const timer = () => {
      console.log(this.props); // should be defined
    };

    const timerLeft = setInterval(timer, 1000);
  }
}

这是有效的,因为使用箭头函数,this设置为封闭上下文的this