刷新后React-Redux状态丢失

问题描述 投票:0回答:7

我对 React 和 Redux 非常陌生,我一直在学习 Stephen Grider 的高级 React 和 Redux 课程,并且正在做身份验证的客户端。我已经在本地存储中保存了一个令牌,并且一切似乎都工作正常,直到我刷新页面。当我登录/注册时,导航会更改为显示注销按钮,但如果我手动刷新页面,导航会更改回显示登录/注册按钮。

我对此真的很陌生,不知道应该包含什么作为代码片段。我将保留减速器和 actions/index.js。另外 this 也很喜欢我的 git 存储库。

动作/index.js

import axios from 'axios';
import { browserHistory } from 'react-router';
import { push } from 'react-router-redux';
import { AUTH_USER, UNAUTH_USER, AUTH_ERROR } from './types';

const API_URL = 'http://localhost:3000';

export function signinUser({ username, password }) {
  return function(dispatch) {
    // Submit username/password to the server
    axios
      .post(`${API_URL}/signin`, { username, password })
      .then(response => {
        // If request is good...
        // - Update state o indicate user is authenticated
        dispatch({ type: AUTH_USER });
        // - Save the JWT token to local storage
        localStorage.setItem('token', response.data.token);
        // - Redirect to the route '/feature'
        browserHistory.push('/feature');
      })
      .catch(() => {
        // If request is bad...
        // -Show an error to the user
        dispatch(authError('Bad login info'));
      });
  };
}

export function signupUser({ username, email, password }) {
  return function(dispatch) {
    axios
      .post(`${API_URL}/signup`, { username, email, password })
      .then(response => {
        dispatch({ type: AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/feature');
      })
      .catch(response => {
        // TODO
        console.log(response);
        dispatch(authError('There was an error'));
      });
  };
}

export function authError(error) {
  return {
    type: AUTH_ERROR,
    payload: error
  };
}

export function signoutUser() {
  localStorage.removeItem('token');
  return { type: UNAUTH_USER };
}

reducer/auth_reducer.js

import { AUTH_USER, UNAUTH_USER, AUTH_ERROR } from '../actions/types';
export default function(state = {}, action) {
  switch (action.type) {
    case AUTH_USER:
      return { ...state, error: '', authenticated: true };
    case UNAUTH_USER:
      return { ...state, authenticated: false };
    case AUTH_ERROR:
      return { ...state, error: action.payload };
  }

  return state;
}

提前致谢,如果您需要任何额外的代码片段,请告诉我。

javascript reactjs redux
7个回答
19
投票

不要重新发明轮子

要在页面刷新后存储 redux 状态,您可以使用

https://www.npmjs.com/package/redux-persist

它易于实施且稳健。


15
投票

在您的reducer 文件reducer/auth_reducer.js 中,您可以定义reducer 的初始状态。

const initialState = { 
user: localStorage.getItem('user'), foo:'bar',
};

export default function(state = initialState, action) {
    ...

在您的初始状态中,您可以从本地存储或 cookie 加载内容(对于身份验证内容,cookie 是首选)。

initialState 也可以在 createStore 中设置。由你决定。您需要初始状态的地方。我对路线使用异步,因此无法使用 createStore 来保存所有初始状态,因为某些路线可能永远不会被加载。

const initialState = {
  user: localStorage.getItem('user'),
};

const store = createStore(mainReducer, initialState);

您可以使用一个名为 redux-persist 的库。这将使您能够更好地控制要保留的状态。 (https://github.com/rt2zz/redux-persist


10
投票

[编辑 2024]:按照

this
答案中的建议使用 redux-persist


要通过页面刷新保留 Redux 状态,您需要将应用程序状态存储在

localStorage
中并在页面加载时检索它来持久化它。尝试在
componentDidMount
组件的
App
中调度一个操作,该操作从
localStorage

检索数据

8
投票

您需要将应用程序状态保存在本地存储中。 这里是 redux 的创建者 Dan Abramov 制作的教程。


3
投票

做类似的事情:我在我的项目中使用了这种方法

function saveToLocalStorage(store) {
    try {
        const serializedStore = JSON.stringify(store);
        window.localStorage.setItem('store', serializedStore);
    } catch(e) {
        console.log(e);
    }
}

function loadFromLocalStorage() {
    try {
        const serializedStore = window.localStorage.getItem('store');
        if(serializedStore === null) return undefined;
        return JSON.parse(serializedStore);
    } catch(e) {
        console.log(e);
        return undefined;
    }
}

const persistedState = loadFromLocalStorage();

const store = createStore(reducer, persistedState);

store.subscribe(() => saveToLocalStorage(store.getState()));


0
投票

我们可以设置 store 来监听 sessionStore 或 localStorage 值,这样该值就会被保留,

例如

import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import { createBrowserHistory as createHistory } from 'history';
// import createHistory from 'history/createBrowserHistory';
import rootReducer from '@reducers';
import ApiClient from '@helpers/ApiClient';
import createMiddleware from '@reducers/middleware/clientMiddleware';

export const history = createHistory();

const client = new ApiClient();
const initialState = { users: JSON.parse(window.sessionStorage.getItem('redux') || '{}') };
const enhancers = [];
const middleware = [
  createMiddleware(client),
  thunk,
  routerMiddleware(history)
];

if (process.env.NODE_ENV === 'development') {
  const devToolsExtension = window.devToolsExtension;

  if (typeof devToolsExtension === 'function') {
    enhancers.push(devToolsExtension());
  }
}

const composedEnhancers = compose(
  applyMiddleware(...middleware),
  ...enhancers
);

const store = createStore(
  rootReducer,
  initialState,
  composedEnhancers
);

const storeDataToSessionStorage = () => {
  window.sessionStorage.setItem('redux', JSON.stringify(store.getState().users));
};

store.subscribe(storeDataToSessionStorage);

export default store;

以便用户减速器始终从会话存储中获取初始值。 (您也可以根据您的要求推送到localStorage)


0
投票

请检查这些:-

只需添加一个条件即可

import { AUTH_USER, UNAUTH_USER, AUTH_ERROR } from '../actions/types';
export default function(state = {}, action) {
  switch (action.type) {
    case AUTH_USER:
      return { ...state, error: '', authenticated: localStorage.getItem('token') ? true : false }; // just add this condition here
    case UNAUTH_USER:
      return { ...state, authenticated: localStorage.getItem('token') ? true : false }; // just add this condition here also
    case AUTH_ERROR:
      return { ...state, error: action.payload };
  }

  return state;
}

© www.soinside.com 2019 - 2024. All rights reserved.