Состояние React-Redux потеряно после обновления

Я действительно новичок в React и Redux, я слежу за курсом Стивена Гридера Advanced React и Redux и выполняю аутентификацию на стороне клиента. У меня уже есть токен, сохраненный в моем локальном хранилище, и, казалось, все работало нормально, пока я не обновил страницу. Когда я вхожу/регистрируюсь, навигация изменяется, чтобы отобразить кнопку выхода из системы, но затем, если я вручную обновляю страницу, навигация переключается обратно, чтобы отображать кнопки входа/регистрации.

Я действительно новичок в этом и понятия не имею, что я должен включить в качестве фрагментов кода. Я оставлю редуктор и action/index.js. Также это похоже на мой репозиторий 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 };
}

редуктор /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;
}

Заранее спасибо, если вам нужен дополнительный фрагмент кода, пожалуйста, дайте мне знать.

Ответы

Ответ 1

Чтобы сохранить состояние Redux через обновление страницы, вам необходимо сохранить состояние приложения, сохранив его в localStorage и получить его при загрузке страницы. Попробуйте отправить действие в componentDidMount localStorage componentDidMount вашего App, которое извлекает данные из localStorage

Ответ 2

Вам нужно сохранить состояние приложения в localStorage. Вот урок, сделанный Дэн Абрамовым, создателем редукса.

Ответ 3

В редукционном файле редуктора /auth_reducer.js вы можете определить начальное состояние редуктора.

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

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

в вашем начальном состоянии вы можете загружать материал из localstorage или из файла cookie (cookie предпочтительнее для файлов auth).

initialState также может быть настроен в вашем createStore. Это вам. Где вам нужно исходное состояние. Я использую async для своих маршрутов, поэтому я не могу использовать createStore для хранения всего моего начального состояния, поскольку некоторые маршруты, возможно, никогда не будут загружены.

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

const store = createStore(mainReducer, initialState);

Существует библиотека, которую вы можете использовать с именем redux-persist. Это даст вам больше контроля над тем, какое состояние вы хотите сохранить. (https://github.com/rt2zz/redux-persist)

Ответ 4

Проблема в методе saveState, который заменяет загруженное состояние, поэтому вы должны сохранить его как-то так:

export const saveState = state => {
  try {
    const serializedState = JSON.stringify(mergeDeep(loadState(), state));
    localStorage.setItem('state', serializedState);
  } catch (err) {
    // Ignore write errors.
  }
};

Ответ 5

  не изобретать велосипед

Для сохранения избыточного состояния даже после обновления страницы вы можете использовать

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

Это легко реализовать и надежно.