часть состояния redux изменяется на null, когда я пытаюсь распечатать его в компоненте

#reactjs #redux

#reactjs #redux

Вопрос:

Я пытаюсь отобразить информацию пользователя в компоненте панели мониторинга, просто с помощью простого:

 const mapStateToProps = state => ({
  user: state.authReducer.user
})
  

При входе в систему или регистрации вызываются соответствующие действия, а также действие USER_LOADED; вся информация о пользователе отображается в redux-logger с объектом user, отображающим «имя», «идентификатор» и другую информацию. Однако, когда я пытаюсь опубликовать имя пользователя с

 const Dashboard = ({ user, isAuthenticated }) => {
  return (
    <div>
      {user.name}
    </div>
  )
}
  

все превращается в null, включая значение IsAuthenticated (которое изначально было установлено в true после успешного входа в систему.) Я могу использовать JSON.stringify для объекта user, и он отлично отображает их значения, но если я попытаюсь использовать JSON.stringify с user.name Я получаю ту же ошибку, показанную ниже, где значение становится нулевым.
Почему я должен пытаться перечислить пользовательское состояние redux, чтобы его значение стало нулевым?
Я использую redux-persist (я не знаю, имеет ли это какое-либо отношение к этому)

Dashboard.js (компонент):

 import React from 'react'
import { connect } from 'react-redux';

const Dashboard = ({ user, isAuthenticated, token }) => {
  return (
    <div>
     {user.name}
    </div>
  )
}

const mapStateToProps = state => ({
  user: state.authReducer.user
})
export default connect(mapStateToProps)(Dashboard);

  

authReducer.js:

 import {
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_FAIL,
  LOGIN_SUCCESS,
  LOGOUT,
  ACCOUNT_DELETED
} from '../../actions/types';

const initialState = {
  token: localStorage.getItem('token'),
  isAuthenticated: null,
  loading: true,
  user: null
}

const authReducer = (state = initialState, action) => {
  const { type, payload } = action;

  switch (type) {
    case USER_LOADED:
      return {
        ...state,
        isAuthenticated: true,
        loading: false,
        user: payload
      }
    case REGISTER_SUCCESS:
    case LOGIN_SUCCESS:
      localStorage.setItem('token', payload.token);
      return {
        ...state,
        ...payload,
        isAuthenticated: true,
        loading: false
      }

    case REGISTER_FAIL:
    case AUTH_ERROR:
    case LOGIN_FAIL:
    case LOGOUT:
    case ACCOUNT_DELETED:
      localStorage.removeItem('token');
      return {
        ...state,
        token: null,
        isAuthenticated: false,
        loading: false
      }

    default:
      return state;
  }
}

export default authReducer;
  

аутентификация (действия):

 import axios from 'axios';
import { setAlert } from './alert';

import {
  REGISTER_SUCCESS,
  REGISTER_FAIL,
  USER_LOADED,
  AUTH_ERROR,
  LOGIN_FAIL,
  LOGIN_SUCCESS,
  LOGOUT,
  CLEAR_PROFILE
} from './types';

import setAuthToken from '../utils/setAuthToken';

//LOAD USER
export const loadUser = () => async dispatch => {
  if (localStorage.token) {
    setAuthToken(localStorage.token);
  }

  try {
    const res = await axios.get('/api/auth');

    dispatch({
      type: USER_LOADED,
      payload: res.data
    })
  } catch (err) {
    dispatch({
      type: AUTH_ERROR
    })
  }
}

//Register user
export const register = ({ name, email, password }) => async dispatch => {
  const config = {
    headers: {
      'Content-Type': 'application/json'
    }
  }

  const body = JSON.stringify({ name, email, password });

  try {
    const res = await axios.post('/api/users', body, config);

    dispatch({
      type: REGISTER_SUCCESS,
      payload: res.data
    });

    dispatch(loadUser());

  } catch (err) {
    const errors = err.response.data.errors;
    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
    }

    dispatch({
      type: REGISTER_FAIL
    })
  }
}

//Login user
export const login = (email, password) => async dispatch => {
  const config = {
    headers: {
      'Content-Type': 'application/json',
    }
  }

  const body = JSON.stringify({ email, password });

  try {
    const res = await axios.post('/api/auth', body, config);

    dispatch({
      type: LOGIN_SUCCESS,
      payload: res.data
    });

    dispatch(loadUser());
  } catch (err) {
    const errors = err.response.data.errors;
    if (errors) {
      errors.forEach(error => dispatch(setAlert(error.msg, 'danger')));
    }

    dispatch({
      type: LOGIN_FAIL
    })
  }
}

//Logout clear profile
export const logout = () => dispatch => {
  dispatch({
    type: CLEAR_PROFILE
  });
  dispatch({
    type: LOGOUT
  });

}
  

auth.js (маршрут, который аутентифицирует пользователя / получает токен):

 const express = require('express');
const router = express.Router();
const auth = require('../../middleware/auth');
const User = require('../../models/User');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const config = require('config');
const { check, validationResult } = require('express-validator');

//@route GET api/auth
//@desc Test route
//@access Public
router.get('/', auth, async (req, res) => {
  try {
    const user = await User.findById(req.user.id).select('-password');
    res.json(user);
  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server error');
  }
});

//@route POST api/auth
//@desc Authenticate user and get token
//@access Public
router.post('/', [
  check('email', 'Please include a valid email').isEmail(),
  check('password', 'Password is required').exists()
], async (req, res) => {
  const errors = validationResult(req);

  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() })
  }

  const { email, password } = req.body;

  try {
    let user = await User.findOne({ email })

    if (!user) {
      return res.status(400).json({ errors: [{ msg: 'Invalid credentials' }] })
    }


    const isMatch = await bcrypt.compare(password, user.password);

    if (!isMatch) {
      return res.status(400).json({ errors: [{ msg: 'Invalid credentials' }] });
    }

    const payload = {
      user: {
        id: user.id
      }
    }
    jwt.sign(payload,
      config.get('jwtSecret'),
      { expiresIn: 360000 },
      (err, token) => {
        if (err) throw error;
        res.json({ token })
      });

  } catch (err) {
    console.error(err.message);
    res.status(500).send('Server error');
  }


});

module.exports = router;
  

значения redux на домашней странице:
введите описание изображения здесь

Я нажимаю на панель инструментов, и похоже, что хранилище сбрасывается:
введите описание изображения здесь я получаю эту ошибку при попытке отобразить любую часть пользовательского объекта : введите описание изображения здесь

Комментарии:

1. пожалуйста, поделитесь целой кучей кода. @connect, reducer и так далее. сложно разобраться в проблеме по частям.

2. @AlexanderAlexandrov Я добавил соответствующий редуктор, компонент, файл действий и файл маршрута. Пожалуйста, дайте мне знать, если я что-то упустил, и спасибо за исправление.

3. пользователь имеет значение null в intialState . Таким образом, первоначальный рендеринг завершается с ошибкой NPE. Может быть, внутри Dashboard компонента требуется какая-то защита?

4. @AlexanderAlexandrov Это похоже на сброс хранилища при переходе на панель мониторинга (защищенный маршрут).) Я включил две картинки, которые показывают хранилище домашней страницы (с пользовательским объектом) и после перехода на панель мониторинга (похоже, это сбрасывает хранилище).) Может быть, redux сохраняется, возвращаясь к исходному состоянию?

5. Обновление, при входе в систему он правильно перенаправляется на панель мониторинга, где отображается имя пользователя. Однако, если я обновляю страницу, у меня все еще есть токен в состоянии Redux, но user и IsAuthenticated имеют значение null, при этом вызываются действия PERSIST и REHIDRATE. Редуктор аутентификации включен в постоянное хранилище, поэтому я не уверен, почему он сбрасывается. Другие значения сохраняются при обновлении, поэтому это довольно странно.

Ответ №1:

Ответил, у меня не было моего редуктора аутентификации в белом списке моего объекта persistConfig в моем корневом редукторе. Данные не сохранялись, поскольку они не были указаны для сохранения facepalm