react / redux无法读取未定义的属性'setCurrent'

时间:2018-07-09 20:17:49

标签: javascript reactjs redux react-redux

因此即时通讯正在为我的项目准备redux并陷入困境。 一切似乎都正确,因为redux devtools显示了状态。

当我尝试通过this.props.function_name

调用组件中的函数时,会出现问题

我在.then()中执行该调用,因为当axios返回令牌时正在调用它,我知道此范围会在那时发生变化,但是我当时正在使用arrow函数,因此问题似乎不存在

也尝试从另一个函数调用this.props.setcurrent,但是得到了  _this2未定义 我的代码:

Signup.js

import {setCurrent} from '../actions/authActions'

class SignUp extends Component {
  constructor(props) {
    super(props);
  }
  responseGoogle(response) {
    console.log('google', response);
    const access_token = response.Zi.access_token;
    axios
      .post('http://localhost:3001/users/oauth/google', {
        access_token
      })
      .then((response) =>{
        console.log('google', response);
        const decoded = jwt_decode(response.data.token);
        this.props.setCurrent(decoded);
        console.log(decoded);
      })
      .catch(function (error) {
        console.log(error);
      });
  }
  render() {
    return (
          <GoogleLogin
            clientId="890644813294-bvuq6cf7lsilohneqvov28oi60sfdmig.apps.googleusercontent.com"
            buttonText="Login"
            onSuccess={this.responseGoogle}
            onFailure={this.responseGoogle}
          />
       )
  }
}

export default connect(null, { setCurrent })(SignUp);

authActions.js

import { TEST_DISPATCH } from './types';

// Testing
export const setCurrent = (userToken) => {
  return {
    type: TEST_DISPATCH,
    payload: userToken
  };
};

authReducer.js

import { TEST_DISPATCH } from '../actions/types';
const initialState = {
  isAuthenticated: false,
  user: {}
}
export default function(state = initialState, action) {
  switch(action.type) {
    case TEST_DISPATCH:
      return {
        ...state,
        user: action.payload
      };
    default:
      return state;
  }
}

Auth / index.js

import { combineReducers } from 'redux';
import authReducer from './authReducer';

export default combineReducers({
  auth: authReducer
});

store.js

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const initialState = {};

const middleware = [thunk];

const store = createStore(
  rootReducer,
  initialState,
  compose(
    applyMiddleware(...middleware),
   // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )
);

export default store;

App.js

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import store from '../store';
import LogIn from './LogIn';
import SignUp from './SignUp';


class App extends Component {
  render() {
    return(
      <Provider store={ store }>
      <div>
      <h1>SignUp!</h1>
      <SignUp />
    </div>
    </Provider>
    )
  }
}
export default App;

完整代码:https://github.com/ExadelPraktika/Front-exabook/tree/auth 我也在webpack上使用babel

2 个答案:

答案 0 :(得分:3)

  

我知道那时范围会发生变化,但是我当时使用的是箭头功能,因此问题似乎不存在。

这仍然是一个范围问题。方法responseGoogle是作用域的。因此,您需要像这样“自动绑定”它:

responseGoogle = (response) => { /* Your code */ }

:SignUp组件的呈现方法:

<GoogleLogin
    onSuccess={response => this.responseGoogle(response)}
    onFailure={response => this.responseGoogle(response)}
/>

答案 1 :(得分:1)

您对this的引用错误上下文的想法是正确的。在查看此代码段时,我添加了一些注释,这些注释可能有助于澄清。

class SignUp extends Component {
  constructor(props) {
    super(props);
  }

  responseGoogle(response) {
    // "this" does not refer to the class instance here when invoked by
    // the click handler (it is undefined)

    const access_token = response.Zi.access_token;
    axios
      .post('http://localhost:3001/users/oauth/google', {
        access_token
      })
      .then((response) => {
        // Because this is a lambda function, "this" is the same lexical scope
        // as the outer function - but the outer function "this" is undefined
        // *not* the instance of the class (see above)     

        const decoded = jwt_decode(response.data.token);
        this.props.setCurrent(decoded);
        console.log(decoded);
      })
      .catch(function (error) {
        console.log(error);
      });
  }

  render() {
    return (
          <GoogleLogin
            clientId="890644813294-bvuq6cf7lsilohneqvov28oi60sfdmig.apps.googleusercontent.com"
            buttonText="Login"
            onSuccess={this.responseGoogle}
            onFailure={this.responseGoogle}
          />
       )
  }
}

有两种常见的解决方法:

在构造函数中使用bind

class SignUp extends Component {
      constructor(props) {
        super(props);
        this.responseGoogle = this.responseGoogle.bind(this);
      }

      responseGoogle(response) {
        const access_token = response.Zi.access_token;
        axios
          .post('http://localhost:3001/users/oauth/google', {
            access_token
          })
          .then((response) => {
            // Because this is a lambda function, "this" is the same lexical scope
            // as the outer function - but the outer function "this" is undefined
            // *not* the instance of the class (see above)     

            const decoded = jwt_decode(response.data.token);
            this.props.setCurrent(decoded);
            console.log(decoded);
          })
          .catch(function (error) {
            console.log(error);
          });
      }

      render() {
        return (
              <GoogleLogin
                clientId="890644813294-bvuq6cf7lsilohneqvov28oi60sfdmig.apps.googleusercontent.com"
                buttonText="Login"
                onSuccess={this.responseGoogle}
                onFailure={this.responseGoogle}
              />
           )
      }
    }

JavaScript的bind方法存在于函数中,并返回一个与原始函数相同的新函数,但其​​上下文(其“ this”)设置为传递给bind的任何东西。因此,我们创建了一个新方法,该方法绑定到构造函数中的任何“ this”。在构造函数中,“ this”是类实例,因此在点击处理程序中也是如此。

使用lambda函数代替类方法

class SignUp extends Component {
    responseGoogle = (response) => {
        const access_token = response.Zi.access_token;
        axios
          .post('http://localhost:3001/users/oauth/google', {
            access_token
          })
          .then((response) =>{
            console.log('google', response);
            const decoded = jwt_decode(response.data.token);
            this.props.setCurrent(decoded);
            console.log(decoded);
          })
          .catch(function (error) {
            console.log(error);
          });
      }
      render() {
        return (
              <GoogleLogin
                clientId="890644813294-bvuq6cf7lsilohneqvov28oi60sfdmig.apps.googleusercontent.com"
                buttonText="Login"
                onSuccess={this.responseGoogle}
                onFailure={this.responseGoogle}
              />
           )
      }
  }

由于保持外部“ this”的原因,对.then的lambda函数回调起作用的原因相同。该方法的唯一缺点是它不是JS语言的真正组成部分,因此您需要进行翻译才能使其正常工作(但是您已经在使用babel / webpack了,所以这不是问题)