Redux - MapDispatchToProps Not Working For Logout Function
in my app I've a logout button but it does not log you out. I've checked the reducers and the actions and they seem okay as I've another similar app and it works there.
This is the "Nav.jsx" component where the logout action is being imported.
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)
When I run this, the console.log give me "is this logout? ƒ () { [native code] }" and I also get this warning: "Hash history cannot PUSH the same path; a new entry will not be added to the history stack". This was a group project that I'm now working on myself and I can't tell what exactly is wrong? Please help.
Here is the logout action if it helps.
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())
}
}
Here are some more files from the app.This is the auth.js in the reducers folder.
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
}
}
And the index.js where the reducers have been combined.
import {combineReducers} from 'redux'
import auth from './auth'
import lostPets from './lostPets'
import found from './foundPets'
export default combineReducers({
auth,
found,
lostPets
})
Answer
You need to call the function directly instead of using dispatch since you are already using mapDispatchToProps
, If you don't provide mapDispatchToProps
, dispatch
will be made available to the component
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)
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM