Redux - mapDispatchToProps 不适用于注销功能
Redux - mapDispatchToProps not working for logout function
在我的应用程序中,我有一个注销按钮,但它不会让您注销。我已经检查了 reducers 和 action,它们看起来没问题,因为我有另一个类似的应用程序并且它在那里工作。
这是正在导入注销操作的 "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 给我 "is this logout? ƒ () { [native code] }" 并且我也收到这个警告:"Hash history cannot PUSH the same path; a new entry will not be added to the history stack"。这是一个我现在正在做的小组项目,我不知道到底哪里出了问题?请帮忙。
如果有帮助,这是注销操作。
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.This 的更多文件是 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 reducer 合并的地方。
从 'redux'
导入 {combineReducers}
import auth from './auth'
import lostPets from './lostPets'
import found from './foundPets'
export default combineReducers({
auth,
found,
lostPets
})
您需要直接调用该函数而不是使用调度,因为您已经在使用 mapDispatchToProps
,如果您不提供 mapDispatchToProps
,dispatch
将提供给组件
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)
我不明白你为什么要同时使用组件状态和 redux 状态来跟踪用户是否已注销。无论如何,您将 dispatch
传递给 mapDispatchToProps,并且应该使用 dispatch()
包装您在 mapDispatchToProps 中定义的函数,以便它们被发送到调度程序:
const mapDispatchToProps = dispatch => ({
logout: () => dispatch(logoutUser())
})
使用这种模式可以让您将所有调度呼叫集中在 mapDispatchToProps
内。
Full reducer(我将状态初始化为已登录,因为我无权访问您实际对用户进行身份验证的 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)
我认为您在继续操作或在 Whosebug 上提问之前需要大大简化。制作一个简单的组件应用程序,其中包含一个 div,允许用户单击以登录并单击以注销。然后一一介绍元素。当您遇到困难时,将应用程序缩减到问题的绝对最小可行表达,post 在这里作为一个问题,人们会很乐意提供帮助...
在我的应用程序中,我有一个注销按钮,但它不会让您注销。我已经检查了 reducers 和 action,它们看起来没问题,因为我有另一个类似的应用程序并且它在那里工作。
这是正在导入注销操作的 "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 给我 "is this logout? ƒ () { [native code] }" 并且我也收到这个警告:"Hash history cannot PUSH the same path; a new entry will not be added to the history stack"。这是一个我现在正在做的小组项目,我不知道到底哪里出了问题?请帮忙。
如果有帮助,这是注销操作。
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.This 的更多文件是 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 reducer 合并的地方。
从 'redux'
导入 {combineReducers}import auth from './auth'
import lostPets from './lostPets'
import found from './foundPets'
export default combineReducers({
auth,
found,
lostPets
})
您需要直接调用该函数而不是使用调度,因为您已经在使用 mapDispatchToProps
,如果您不提供 mapDispatchToProps
,dispatch
将提供给组件
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)
我不明白你为什么要同时使用组件状态和 redux 状态来跟踪用户是否已注销。无论如何,您将 dispatch
传递给 mapDispatchToProps,并且应该使用 dispatch()
包装您在 mapDispatchToProps 中定义的函数,以便它们被发送到调度程序:
const mapDispatchToProps = dispatch => ({
logout: () => dispatch(logoutUser())
})
使用这种模式可以让您将所有调度呼叫集中在 mapDispatchToProps
内。
Full reducer(我将状态初始化为已登录,因为我无权访问您实际对用户进行身份验证的 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)
我认为您在继续操作或在 Whosebug 上提问之前需要大大简化。制作一个简单的组件应用程序,其中包含一个 div,允许用户单击以登录并单击以注销。然后一一介绍元素。当您遇到困难时,将应用程序缩减到问题的绝对最小可行表达,post 在这里作为一个问题,人们会很乐意提供帮助...