【问题标题】:React-Redux state lost after refresh刷新后 React-Redux 状态丢失
【发布时间】:2018-03-22 05:49:08
【问题描述】:

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

我对此真的很陌生,不知道我应该在代码 sn-ps 中包含什么。我将留下 reducer 和 actions/index.js。 this 也是我的 git 存储库的一个赞。

actions/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;
}

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

【问题讨论】:

  • 您是否正在尝试执行localStorage.getItem('token') 并在应用安装后立即登录用户?因为它不会自行发生。
  • 要明确:刷新页面时所有state都会丢失;您想要保存的任何内容都必须手动保存和恢复。

标签: javascript reactjs redux


【解决方案1】:

不要重新发明轮子

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

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

它易于实现且健壮。

【讨论】:

    【解决方案2】:

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

    const initialState = { 
    user: localStorage.getItem('user'), foo:'bar',
    };
    
    export default function(state = initialState, action) {
        ...
    

    在您的 initialState 中,您可以从 localstorage 或 cookie 加载内容(对于 auth 内容,cookie 是首选)。

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

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

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

    【讨论】:

      【解决方案3】:

      要通过页面刷新来保留 Redux 状态,您需要通过将其存储在 localStorage 中来持久化应用程序状态并在页面加载时检索它。尝试在App 组件的componentDidMount 中调度一个操作,该操作从localStorage 检索数据

      【讨论】:

        【解决方案4】:

        您需要在 localStorage 中保存应用程序状态。 Here 是 redux 的创建者 Dan Abramov 制作的教程。

        【讨论】:

        • @Sergiu Dan Abramov 是 Redux 的创建者,也是 Create React App(而非 React)的合著者。 Jordan Walke 在 Facebook 创建了 React。它在 React 的维基百科上......
        【解决方案5】:

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

        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()));

        【讨论】:

          【解决方案6】:

          我们可以设置 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;
          

          这样用户reducer 总是从会话存储中获取初始值。 (也可以根据自己的需求推送到localStorage)

          【讨论】:

            猜你喜欢
            • 2019-02-09
            • 2020-04-30
            • 1970-01-01
            • 1970-01-01
            • 2018-05-29
            • 1970-01-01
            • 2019-11-02
            • 2018-09-25
            • 1970-01-01
            相关资源
            最近更新 更多