我有一个使用 React 和 Redux 构建的简单的“类似帖子”应用程序。当用户登录时,他应该看到一个导航栏,当他没有登录时,他应该看到另一个。
我正在使用 redux-devtools 来跟踪状态变化。
问题是,当我登录时,我设置了一个本地存储令牌,当我注销时,我将该令牌设置为空。这种方法工作正常,当我单击注销时,我在 redux devtools 中看到令牌为
null
和 user_authenticated
为 false,但是当我返回主页或单击浏览器后退按钮时,它会恢复为login
状态,然后我可以看到令牌值并且is_authenticated
被设置为true。
当我刷新页面时,我得到了我想要的行为,即用户注销,令牌设置为 null,并且
is_authenticated
设置为 false。
奇怪的是,如果我这样做
console.log(store.getState())
,我会在那里得到更新/预期的状态,但开发工具显示以前的状态,并且页面甚至表现得像以前的状态。
登录的情况也是如此,在导航中来回移动可以让我回到我第一次访问该页面时的旧状态。
退出后,返回主页后,来自我的 redux-devtools 的状态。
user: {
is_authenticated: true,
token: 'c80c632a6529b79d51fd3e2fc915cfb94834aa5237b4e65924c095ea58f289b3',
is_loading: false
},
从注销返回后,同一页面上
store.getState()
的状态
user:
is_authenticated: false
is_loading: false
token: "null"
下面列出了我的一些组件:
routes.js
import { Switch, Route } from 'react-router-dom';
import React, {Component} from 'react';
import Homepage from './components/homepage';
import Scammer from './components/scammer';
import ScammerCreate from './components/scammer_create'
import Navbar from './components/navbar'
import Register from './components/register'
import Login from './components/login'
import Logout from './components/logout'
import {store} from './index'
class Routes extends Component {
componentWillMount() {
store.dispatch({
type: 'get_user',
})
store.getState()
}
render(){
return(
<div>
<Navbar />
<Switch>
<Route path="/" exact component={Homepage}/>
<Route path="/scammer/create" exact component={ScammerCreate}></Route>
<Route path="/scammer/:id" exact component={Scammer}/>
<Route path="/auth/register" exact component={Register}></Route>
<Route path="/auth/login" exact component={Login}></Route>
<Route path="/auth/logout" exact component={Logout}></Route>
</Switch>
</div>
)
}
}
export default Routes;
索引.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import promiseMiddleware from 'redux-promise';
import thunkMiddleware from 'redux-thunk'
import Routes from './routes'
import rootReducer from './reducers/index';
//const createStoreWithMiddleware = applyMiddleware(promiseMiddleware)(createStore)
const middleware = [promiseMiddleware,thunkMiddleware]
export const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(...middleware))
)
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<Routes/>
</BrowserRouter>
</Provider>
, document.getElementById('root'));
用户减速器
let initialState = {
}
if (localStorage.getItem('token') != null && localStorage.getItem('token') != 'null'){
initialState['is_authenticated'] = true;
initialState['token'] = localStorage.getItem('token');
initialState['is_loading'] = false;
}
else{
initialState ={
'is_authenticated' : false,
'token' : localStorage.getItem('token'),
'is_loading' : false,
}
}
export default function user(state=initialState,action){
if (action.type == "registered") {
localStorage.setItem('token',action.payload.token);
return {...state, 'user_details': action.payload.user,'token':localStorage.getItem('token'),'is_authenticated':true,'is_loading':false}
}
else if ( action.type == "login" ){
console.log(action.payload)
localStorage.setItem('token',action.payload.token)
return {
...state,'is_authenticated' : true, 'token' : localStorage.getItem('token'),'is_loading' : false,
'user_details' : action.payload.user,
}
}
else if( action.type == "logout" ){
localStorage.setItem("token",null);
return {
...state,'is_authenticated' : false, 'token' : localStorage.getItem('token'), 'is_loading' : false
}
}
else if(action.type == 'get_user'){
const token = localStorage.getItem('token');
console.log(token)
if (token != null && token != 'null'){
return {
...state,'is_authenticated' : true, token : token, is_loading : false,
}
}
else {
return {
...state, is_authenticated : false, token: token, is_loading : false,
}
}
}
else{
return initialState;
}
}
好吧,经过几天的调试,并从头到尾浏览了 redux 教程,但仍然失败。
我终于意识到我正在返回默认操作的初始状态。因此,当加载新组件时,它将获得初始状态而不是更新状态。
Redux 减速器应该始终返回状态值。在您的情况下,问题是默认返回 initial 状态而不是 current 状态。
更新减速器以与 Redux 减速器建议的模式保持一致。
示例:
export default function user(state = initialState, action) {
switch (action.type) {
case "registered":
localStorage.setItem('token', action.payload.token);
return {
...state,
user_details: action.payload.user,
token: localStorage.getItem('token'),
is_authenticated: true,
is_loading: false
};
case "login":
localStorage.setItem('token',action.payload.token)
return {
...state,
is_authenticated: true,
token: localStorage.getItem('token'),
is_loading: false,
user_details: action.payload.user,
};
case "logout":
localStorage.setItem("token",null);
return {
...state,
is_authenticated: false,
token: localStorage.getItem('token'),
is_loading: false
};
case "get_user":
const token = localStorage.getItem('token');
return {
...state,
is_authenticated: token != null && token != 'null',
token,
is_loading: false,
};
default:
return state; // <-- no case matched, return current state
}
}