派遣行动后道具未更新

时间:2019-08-08 21:23:58

标签: javascript node.js reactjs redux react-redux


我正在尝试使用React / Redux / Node.js实现Twitter身份验证。后端部分工作正常,因为前端获取了正确的数据。 我现在面临的问题是前端。更具体地,当在成功认证之后接收到令牌时,调度动作,从而结果props被更新。但是,这不会发生。这是代码:

Header.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import TwitterLogin from 'react-twitter-auth';
import { connect } from 'react-redux';
import { loginSuccess, logout } from './redux/actions/actions';

import 'bulma/css/bulma.css';

class Header extends Component {

  constructor(props) {
    super(props);

    this.onSuccess = this.onSuccess.bind(this);
    this.onFailed = this.onFailed.bind(this);
  }

  onSuccess = (response) => {
    const token = response.headers.get('x-auth-token');
    response.json().then(user => {
      if (token) {
        this.props.loginSuccess(user, token);
      }
    });
  };

  onFailed = (error) => {
    alert(error);
  };

  logout = () => {
    this.props.logout();
  };

  render() {
    let content = this.props.isAuthenticated === true ?
      (
        <div>
          <div>
            <Link className="button is-primary" to="/profile">Profile</Link>
            <button onClick={this.logout} className="button" >
              Log out
            </button>
          </div>
        </div>
      ) :
      (
        <TwitterLogin 
          loginUrl="http://localhost:5000/api/auth/twitter"
          onFailure={this.onFailed} onSuccess={this.onSuccess}
          requestTokenUrl="http://localhost:5000/api/auth/twitter/reverse"
          className="button" />
      );


    return (
      <header className="navbar has-shadow is-spaced">
        <div className="container">
          <div className="navbar-brand">
            <h1 className="title is-4">
              <Link to="/" className="navbar-item">
                <strong>App</strong>
              </Link>
            </h1>
          </div>
          <div className="navbar-end">
            <div className="buttons">
              {content}
            </div>
          </div>
        </div>
      </header>
    );
  }
}

const mapStateToProps = ({token, user, isAuthenticated}) => ({token, user, isAuthenticated});

export default connect(
  mapStateToProps,
  {loginSuccess,
  logout})(Header);

actions.js

export const loginSuccess = (user, token) => {
  return (dispatch) => {
    dispatch({type: 'LOGIN_SUCCESS', payload: {user, token}})
  }
}

reducers.js

const initialState = {
  token: null,
  user: null,
  isAuthenticated: false,
  error: false
};

export default (state=initialState, action) => {
  switch (action.type) {
    case 'LOGOUT':
      localStorage.removeItem('user');
      return initialState;
    case 'LOGIN_ERROR':
      return {
        ...state,
        error: true
      }
    case 'LOGIN_SUCCESS':
      return {
        token: action.payload.token,
        user: action.payload.user,
        isAuthenticated: true,
        error: false
      }
    default:
      return state;
  }
}

store.js

import {applyMiddleware, createStore} from 'redux';
import thunkMiddleware from 'redux-thunk';
import reducer from './reducer';

const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);

export const store = createStoreWithMiddleware(reducer);

我在这里想念什么? onSuccess 函数中缺少什么吗?
谢谢!

2 个答案:

答案 0 :(得分:0)

请尝试替换

    case 'LOGIN_SUCCESS':
  return {
    token: action.payload.token,
    user: action.payload.user,
    isAuthenticated: true,
    error: false
  }

作者:

    case 'LOGIN_SUCCESS':
  return {
    ...state,token: action.payload.token,
    user: action.payload.user,
    isAuthenticated: true,
    error: false
  }

答案 1 :(得分:0)

我发现了问题!我以错误的方式声明了mapStateToProps
正确的代码如下:

Header.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import TwitterLogin from 'react-twitter-auth';
import { connect } from 'react-redux';
import { loginSuccess, logout } from './redux/actions/actions';

import 'bulma/css/bulma.css';

class Header extends Component {

  constructor(props) {
    super(props);

    this.onSuccess = this.onSuccess.bind(this);
    this.onFailed = this.onFailed.bind(this);
  }

  onSuccess = (response) => {
    const token = response.headers.get('x-auth-token');
    response.json().then(user => {
      if (token) {
        this.props.loginSuccess(user, token);
      }
    });
  };

  onFailed = (error) => {
    alert(error);
  };

  logout = () => {
    this.props.logout();
  };

  render() {
    let content = this.props.users.isAuthenticated === true ?
      (
        <div>
          <div>
            <Link className="button is-primary" to="/profile">Profile</Link>
            <button onClick={this.logout} className="button" >
              Log out
            </button>
          </div>
        </div>
      ) :
      (
        <TwitterLogin 
          loginUrl="http://localhost:5000/api/auth/twitter"
          onFailure={this.onFailed} onSuccess={this.onSuccess}
          requestTokenUrl="http://localhost:5000/api/auth/twitter/reverse"
          className="button" />
      );


    return (
      <header className="navbar has-shadow is-spaced">
        <div className="container">
          <div className="navbar-brand">
            <h1 className="title is-4">
              <Link to="/" className="navbar-item">
                <strong>App</strong>
              </Link>
            </h1>
          </div>
          <div className="navbar-end">
            <div className="buttons">
              {content}
            </div>
          </div>
        </div>
      </header>
    );
  }
}

const mapStateToProps = ({users}) => ({users});

export default connect(
  mapStateToProps,
  {loginSuccess,
  logout})(Header);

以下是我结合减速器的代码:

reducer.js

import { combineReducers } from 'redux';
import users from './reducers/users';
import polls from './reducers/polls';

export default combineReducers({
    users,
    polls
});

通过使用此代码,我可以看到在调度动作之后更新了道具。
感谢您的帮助!