в моем приложении есть кнопка выхода из системы, но она не выводит вас из системы. Я проверил редукторы и действия, и они кажутся нормальными, поскольку у меня есть другое похожее приложение, и оно там работает.
Это компонент «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.info("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.info сообщает мне: «Это выход из системы? Ƒ () {[native code]}», и я также получаю это предупреждение: «Хеш-история не может PUSH по тому же пути; новая запись не будет добавлена в стек истории ". Это был групповой проект, над которым я сейчас работаю, и я не могу сказать, что именно не так? Пожалуйста помоги.
Вот действие выхода, если это поможет.
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())
}
}
Вот еще несколько файлов из приложения. Это auth.js в папке redurs.
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, где были объединены редукторы.
импортировать {combReducers} из "redux"
import auth from './auth'
import lostPets from './lostPets'
import found from './foundPets'
export default combineReducers({
auth,
found,
lostPets
})
Вы сопоставили свою отправку с реквизитами, поэтому вы не можете использовать this.props.dispatch в этом компоненте. Учитывая это, вы должны использовать this.props.logout вместо своей функции logout(). Попробуйте обновить свой код и посмотрите, что произойдет. Кроме того, похоже, что у вас проблема с react-router.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вам нужно вызвать функцию напрямую, а не использовать диспетчеризацию, поскольку вы уже используете 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.info("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)
Я не понимаю, почему вы используете как состояние компонента, так и состояние редукции, чтобы отслеживать, вышел ли пользователь из системы. В любом случае, вы передаете dispatch в mapDispatchToProps и должны обернуть ваши функции, которые вы определяете внутри mapDispatchToProps, с помощью dispatch(), чтобы они были отправлены диспетчеру:
const mapDispatchToProps = dispatch => ({
logout: () => dispatch(logoutUser())
})
Использование такого шаблона позволит вам сконцентрировать все диспетчерские вызовы внутри mapDispatchToProps.
Полный редуктор (я инициализирую состояние как зарегистрированный, потому что у меня нет доступа к вашему модулю аутентификации, который фактически аутентифицирует пользователей):
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;
Редуктор установлен в состоянии 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.info('logging out')
this.props.logout()
this.setState({loggedOut: true})
}
render() {
//
const {auth} = this.props
const {loggedOut} = this.state
console.info('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, которое позволяет пользователям щелкать для входа в систему и щелкать для выхода. Затем по очереди вводите элементы. Когда вы застряли, сократите приложение до его минимально жизнеспособного выражения проблемы и опубликуйте это как вопрос здесь, и люди будут рады помочь ...
Привет всем, спасибо за ответы, но я все равно получаю те же ошибки.
@Jattsingh, это ваше первое знакомство с React (или с React Router или Redux)? Этот код выглядит довольно запутанным; Я настоятельно рекомендую сначала попытаться создать более простой вариант использования, а затем использовать этот компонент аутентификации ...
@Jattsingh вы смотрели мой обновленный ответ? Попробуйте использовать create-react-app или какой-нибудь абсолютно минимальный шаблон и реализовать вышеизложенное, и вы увидите, что изменения работают ...
Спасибо за все ваши ответы, но, возможно, проблема в другом, я добавил еще код. Это был групповой проект, но я в основном работал над реакциями, а сокращение все еще для меня в новинку.
@Jattsingh, вы использовали приложение create-response-app и компоненты, которые я вставил выше? Если да, то с какими проблемами вы столкнулись? Если нет, я думаю, вам следует попробовать это, чтобы изолировать проблему, с которой вы сталкиваетесь ...
Это работает, спасибо вам большое. Должно быть, изначально была неправильна mapStateToProps. Ваше здоровье.
@Jattsingh ура! Я рада, что у тебя все получилось! Получайте удовольствие от изучения Redux. Учебники Egghead.io очень хороши, если вы еще не проверили их ...
@Jattsingh не стесняйтесь нажимать галочку рядом с этим ответом, чтобы люди могли видеть, что проблема решена!
logoutUser- это вызов API или просто функция