Redux - mapDispatchToProps不适用于注销功能

时间:2018-06-07 10:58:48

标签: javascript reactjs redux logout react-props

在我的应用程序中我有一个注销按钮,但它不会让你退出。我检查了减速器和动作,它们似乎没问题,因为我有另一个类似的应用程序,它在那里工作。

这是导入注销操作的“Nav.jsx”组件。

import React from 'react'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
import {logoutUser} from '../actions/logout'

class Nav extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      showBurger: false,
      loggedOut: false
    }
    this.toggleBurger = this.toggleBurger.bind(this)
    this.logout = this.logout.bind(this)
  }
  toggleBurger() {
    this.setState({showBurger: !this.state.showBurger})
  }

  logout () {
    this.props.dispatch(logoutUser())
    this.setState({loggedOut: true})
  }

  render() {
    //
    const {auth} = this.props
    const {showBurger} = this.state
    const {loggedOut} = this.state
    console.log("is this logout?", this.logout.bind(this))

    return <nav className="navbar">
      <div className="container">
        <div className="navbar-brand">
          <span onClick={this.toggleBurger} className={`navbar-burger burger ${showBurger ? 'is-active': ''}`} data-target="navbarMenuHeroA">
            <span></span>
            <span></span>
            <span></span>
          </span>
        </div>
        <div id="navbarMenuHeroA" className={`navbar-menu ${showBurger ? "is-active" : ''}`}>
          <div className="navbar-end">
            <Link onClick={this.toggleBurget} className="navbar-item" to='/found'>Found</Link>
            <Link onClick={this.toggleBurget} className="navbar-item" to='/lost'>Lost</Link>
            {auth.isAuthenticated
              ? <span>
                <Link onClick={this.toggleBurget} className="navbar-item" to='/foundform'>Foundform</Link>
                <Link onClick={this.toggleBurget} className="navbar-item" to='/lostform'>Lostform</Link>
                <Link to="/" onClick={() => this.logout.bind(this)} className="navbar-item">Logout</Link>
              </span>
              : [
                <Link onClick={this.toggleBurger} className="navbar-item is-large" to='/login'>Login</Link>,
                <Link onClick={this.toggleBurger} className="navbar-item" to='/register'>Register</Link>,
              ]
            }
          </div>
        </div>
      </div>
    </nav>
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    logout: () => dispatch(logoutUser())
  }
}

const mapStateToProps = ({auth}) => {
  return {auth}
}

export default connect(mapStateToProps, mapDispatchToProps)(Nav)

当我运行它时,console.log给我“这是注销?ƒ(){[native code]}”并且我也得到这个警告:“哈希历史记录不能推送相同的路径;新的条目不会被添加到历史堆栈“。这是一个小组项目,我现在正在自己工作,我不知道到底出了什么问题?请帮忙。

如果有帮助,这是退出操作。

   import { removeUser } from '../utils/auth'
    function requestLogout () {
      return {
        type: 'LOGOUT_REQUEST',
        isFetching: true,
        isAuthenticated: true
      }
    }

    function receiveLogout () {
      return {
        type: 'LOGOUT_SUCCESS',
        isFetching: false,
        isAuthenticated: false
      }
    }

    // Logs the user out
    export function logoutUser () {
      return dispatch => {
        document.location = "/#/"
        dispatch(requestLogout())
        removeUser()
        dispatch(receiveLogout())
      }
    }

以下是app中的更多文件。这是reducers文件夹中的auth.js。

import { isAuthenticated, getUserTokenInfo } from '../utils/auth'

const initialState = {
  isFetching: false,
  isAuthenticated: isAuthenticated(),
  user: getUserTokenInfo(),
  errorMessage: ''
}

export default function auth (state = initialState, action) {
  switch (action.type) {
    case 'LOGIN_REQUEST':
      return {
        ...state,
        isFetching: true,
        isAuthenticated: false,
        errorMessage: ''
      }
    case 'LOGIN_SUCCESS':
      return {
        ...state,
        isFetching: false,
        isAuthenticated: true,
        user: action.user
      }
    case 'LOGIN_FAILURE':
      return {
        ...state,
        isFetching: false,
        isAuthenticated: false,
        errorMessage: action.message
      }
    case 'LOGOUT_SUCCESS':
      return {
        ...state,
        isFetching: false,
        isAuthenticated: false,
        user: null
      }
    case 'REGISTER_REQUEST':
      return {
        ...state,
        isFetching: true,
        isAuthenticated: false,
        errorMessage: ''
      }
    case 'REGISTER_FAILURE':
      return {
        ...state,
        isFetching: false,
        isAuthenticated: false,
        errorMessage: action.message
      }
    default:
      return state
  }
}

还有减速器的index.js。

从'redux'

导入{combineReducers}
import auth from './auth'
import lostPets from './lostPets'
import found from './foundPets'

export default combineReducers({
  auth,
  found,
  lostPets
})

2 个答案:

答案 0 :(得分:0)

您需要直接调用该函数,而不是使用调度,因为您已经在使用mapDispatchToProps,如果您没有提供mapDispatchToPropsdispatch将可用于成分

import React from 'react'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
import {logoutUser} from '../actions/logout'

class Nav extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      showBurger: false,
      loggedOut: false
    }
    this.toggleBurger = this.toggleBurger.bind(this)
    this.logout = this.logout.bind(this)
  }
  toggleBurger() {
    this.setState({showBurger: !this.state.showBurger})
  }

  logout () {
    this.props.logout() // call logout here from props
    this.setState({loggedOut: true})
  }

  render() {
    //
    const {auth} = this.props
    const {showBurger} = this.state
    const {loggedOut} = this.state
    console.log("is this logout?", this.logout.bind(this))

    return <nav className="navbar">
      <div className="container">
        <div className="navbar-brand">
          <span onClick={this.toggleBurger} className={`navbar-burger burger ${showBurger ? 'is-active': ''}`} data-target="navbarMenuHeroA">
            <span></span>
            <span></span>
            <span></span>
          </span>
        </div>
        <div id="navbarMenuHeroA" className={`navbar-menu ${showBurger ? "is-active" : ''}`}>
          <div className="navbar-end">
            <Link onClick={this.toggleBurget} className="navbar-item" to='/found'>Found</Link>
            <Link onClick={this.toggleBurget} className="navbar-item" to='/lost'>Lost</Link>
            {auth.isAuthenticated
              ? <span>
                <Link onClick={this.toggleBurget} className="navbar-item" to='/foundform'>Foundform</Link>
                <Link onClick={this.toggleBurget} className="navbar-item" to='/lostform'>Lostform</Link>
                <Link to="/" onClick={() => this.logout.bind(this)} className="navbar-item">Logout</Link>
              </span>
              : [
                <Link onClick={this.toggleBurger} className="navbar-item is-large" to='/login'>Login</Link>,
                <Link onClick={this.toggleBurger} className="navbar-item" to='/register'>Register</Link>,
              ]
            }
          </div>
        </div>
      </div>
    </nav>
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    logout: () => dispatch(logoutUser())
  }
}

const mapStateToProps = ({auth}) => {
  return {auth}
}

export default connect(mapStateToProps, mapDispatchToProps)(Nav)

答案 1 :(得分:0)

我很困惑你为什么要同时使用组件状态和redux状态来跟踪用户是否已注销。无论如何,您将dispatch传递给mapDispatchToProps,并将您在mapDispatchToProps中定义的函数包装为dispatch(),以便将它们发送给调度程序:

const mapDispatchToProps = dispatch => ({
  logout: () => dispatch(logoutUser())
})

使用这种模式,您可以将所有调度调用集中在mapDispatchToProps内。

完全减速器(我初始化状态为登录,因为我无法访问实际验证用户身份的auth模块):

const initialState = {
  isAuthenticated: true,
  isFetching: false,
}

const logoutReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'LOGOUT_REQUEST':
      return Object.assign({}, state, {
        isFetching: true,
      })
    case 'LOGOUT_SUCCESS':
      return Object.assign({}, state, {
        isFetching: false,
        isAuthenticated: false,
      })
    default:
      return state;
  }
}

export default logoutReducer;

Reducer的安装状态为auth:

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

export const rootReducer = combineReducers({
  auth: logoutReducer,
});

完全注销操作:

const requestLogout = () => ({
  type: 'LOGOUT_REQUEST',
  isFetching: true,
  isAuthenticated: true
})

const receiveLogout = () => ({
  type: 'LOGOUT_SUCCESS',
  isFetching: false,
  isAuthenticated: false
})

export const logoutUser = () => {
  return dispatch => {
    document.location = "/#/"
    dispatch(requestLogout())
    //removeUser()
    dispatch(receiveLogout())
  }
}

完整组件:

import React from 'react'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
import {logoutUser} from '../actions/logout'

class Nav extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      showBurger: true,
      loggedOut: false
    }
    this.toggleBurger = this.toggleBurger.bind(this)
    this.logout = this.logout.bind(this)
  }
  toggleBurger() {
    this.setState({showBurger: !this.state.showBurger})
  }

  logout () {
    console.log('logging out')
    this.props.logout()
    this.setState({loggedOut: true})
  }

  render() {
    //
    const {auth} = this.props
    const {loggedOut} = this.state
    console.log('is this logout?', this.logout)

    return <nav className='navbar'>
      <div className='container'>
        <div className='navbar-brand' style={{
            height: '40px',
            width: '40px',
            background: 'red',
          }}>
          <span onClick={this.toggleBurger}
            className={
              `navbar-burger burger ${this.state.showBurger ? 'is-active': ''}`
            } data-target='navbarMenuHeroA'>
            <span></span>
            <span></span>
            <span></span>
          </span>
        </div>
        <div id='navbarMenuHeroA' 
          className={
            `navbar-menu ${this.state.showBurger ? 'is-active' : ''}`
          }>
          <div className='navbar-end'>
            <Link onClick={this.toggleBurger}
              className='navbar-item'
              to='/found'>Found</Link>
            <Link onClick={this.toggleBurger}
              className='navbar-item'
              to='/lost'>Lost</Link>
            {auth.isAuthenticated
              ? <span>
                <Link onClick={this.toggleBurger}
                  className='navbar-item'
                  to='/foundform'>Foundform</Link>
                <Link onClick={this.toggleBurger}
                  className='navbar-item'
                  to='/lostform'>Lostform</Link>
                <Link onClick={this.logout}
                  className='navbar-item'
                  to='/'>Logout</Link>
              </span>
              : [
                <Link onClick={this.toggleBurger}
                  className='navbar-item is-large'
                  to='/login'>Login</Link>,
                <Link onClick={this.toggleBurger}
                  className='navbar-item'
                  to='/register'>Register</Link>,
              ]
            }
          </div>
        </div>
      </div>
    </nav>
  }
}

const mapDispatchToProps = dispatch => ({
  logout: () => dispatch(logoutUser())
})

const mapStateToProps = state => ({
  auth: state.auth,
})

export default connect(mapStateToProps, mapDispatchToProps)(Nav)

我认为在继续处理或在StackOverflow上提问之前,您需要大大简化。使用一个div创建一个简单的单组件应用程序,允许用户单击登录并单击以注销。然后一个接一个地介绍元素。当你遇到困难时,将应用程序削减到问题的绝对最小可行表达,然后将其作为问题发布在此处,人们将很乐意帮助...