Реакция: панель навигации не меняется после передачи токена в localstorage

Я написал компонент навигационной панели, создал 2 константные функции, чтобы отображать их в соответствии с появлением «токена пользователя» в локальном хранилище. После входа в систему с правильными данными я получаю токен пользователя, и он сохраняется в локальном хранилище. Однако он не выполняет повторную визуализацию навигационной панели сразу после того, как маркер пользователя помещается в локальное хранилище. Когда я обновляю страницу, она перерисовывается.

У меня loginForm подключен к состоянию Redux.

Navbar.js

import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';

import './Navbar.css'

class Navbar extends Component {

 logOutHandler(e) {
  e.preventDefault()
  localStorage.removeItem('usertoken')
  this.props.history.push('/login')
 }

 render() {
  const loginRegistrationLink = (
   <ul className='navbar-navigation-dynamic'>
    <li className='navbar-navigation-item'>
      <Link to='/login' className='navbar-navigation-link'>
        Login
      </Link>
    </li>
    <li className='navbar-navigation-item'>
      <Link to='/register' className='navbar-navigation-link'>
        Register
      </Link>
    </li>
  </ul>
)
const profileLink = (
  <ul className='navbar-navigation-dynamic'>
    <li className='navbar-navigation-item'>
      <Link to='/profile' className='navbar-navigation-link'>
        Account
      </Link>
    </li>
    <li className='navbar-navigation-item'>
      <a href='#' onClick = {this.logOutHandler.bind(this)} className='navbar-navigation-link'>
        Logout
      </a>
    </li>
  </ul>
)

return (
  <div className='navbar'>
    <ul className = "navbar-navigation">
      <li className = "navbar-navigation-item">
        <Link to='/' className='navbar-navigation-link'>
          Home
        </Link>
      </li>
    </ul>
    {localStorage.usertoken ? profileLink : loginRegistrationLink}
  </div>
  )
 }
}

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

export default connect(mapStateToProps, {})(withRouter(Navbar));

onSubmitHandler в LoginForm.js

  onSubmitHandler = (e) => {

const { user_name, password } = this.state

      const loggedUser = {
      user_name: user_name,
      password: password
    }
    this.props.loginUser(loggedUser);

    this.setState({
      user_name: '',
      password: ''
    })
  this.props.history.push('/')
  e.preventDefault();
}

действие пользователя

export const loginUser = user => dispatch => {
 axios.post('https://damianlibrary.herokuapp.com/users/login', user)
  .then(res => dispatch({
   type: LOGIN_USER,
   payload: localStorage.setItem('usertoken', res.data)
 }))
}

authReducer.js

import { LOGIN_USER, REGISTER_USER } from '../actions/types';

const authState = {
 users: [],
 status: ''
}

export default function(state = authState, action) {
 switch(action.type) {
  case LOGIN_USER:
   return {
    ...state,
    token: action.payload
   };
  case REGISTER_USER:
   return {
    ...state,
    users: [action.payload, ...state.users], 
    status: action.status
  };
 default:
  return state;
 }
}

Есть ли что-то, связанное с тем, что я не пропустил токен в своем authReducer?

он работает после того, как вы изменили состояние с помощью действия в случае действия LOGIN_USER?

kumarmo2 16.12.2018 15:27

Нет, токен пользователя попадает в локальное хранилище, а после запуска действия входа в систему, я думаю, проблема в том, что панель навигации не отображается.

D.Wasilewski 16.12.2018 15:29

@Wasilewski. что возвращает localStorage.setItem (). если это API-интерфейс localStorage, который предоставляет браузер, то он всегда возвращает undefined после установки пары "ключ-значение" в локальном хранилище.

kumarmo2 16.12.2018 15:30

Возвращает пару ключ-значение. Ключ: usertoken Значение: декодированное значение jwt

D.Wasilewski 16.12.2018 15:31

могу я узнать, какую библиотеку вы используете для установки localStorage?

kumarmo2 16.12.2018 15:32

Я устанавливаю его через функцию localStorage.setItem () в HTTP-запросе axios.

D.Wasilewski 16.12.2018 15:34

и подключается ли ваш компонент Navbar к магазину или получает userToken от любого родительского компонента. Потому что, насколько мне известно, лучшая практика для компонента, отображающего что-то условно, должна полностью зависеть от его состояния, а не от каких-то внешних факторов.

kumarmo2 16.12.2018 15:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
7
1 268
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам нужно передать полезную нагрузку в ваш authreducer. Кроме того, event.preventDefault () следует писать перед history.push ('/') или вы можете писать сразу после вызова функции.

Кроме того, в вашем компоненте входа в систему вы должны вызвать такую ​​функцию:

this.props.dispatch(loginuser()) // pass the input params here 
this.props.history.push('/login')

Вам также необходимо подключить свой компонент к вашему хранилищу redux, как показано ниже:

export default connect (mapStateToProps)(YourComp Name)

Сделал все, что вы сказали, и это не помогло

D.Wasilewski 16.12.2018 15:22

Обновил мой ответ, проверьте это. Я не вижу, чтобы вы использовали mapStateToProps в своем компоненте.

techie_questie 16.12.2018 15:31
Ответ принят как подходящий

It is because your Navbar component is neither connected to the Redux store nor it receives the userToken as props. That is why when your reducer is updating your state, the Navbar is not getting re-rendered.

Also it is always the best practice, to render anything based on either the state or props. Your Navbar component is checking directly in the localStorage for rendering appropriate view. Change it to something like below if you decide to pass the userToken as props to Navbar either from store or parent component.

return (
  <div className='navbar'>
    <ul className = "navbar-navigation">
      <li className = "navbar-navigation-item">
        <Link to='/' className='navbar-navigation-link'>
          Home
        </Link>
      </li>
    </ul>
    {this.props.usertoken ? profileLink : loginRegistrationLink}
  </div>

Все работает нормально после того, как я подключил свой компонент NavBar к магазину. Теперь у меня проблема с обработчиком выхода. Это не вызывает повторной отрисовки. Нужно ли мне добавить новое действие (logoutUser), которое удалит токен для локального хранилища? А потом передать его редуктору?

D.Wasilewski 16.12.2018 16:00

@ D.Wasilewski. Не могли бы вы обновить приведенный выше код?

kumarmo2 16.12.2018 16:03

@ D.Wasilewski. Снова. чтобы запустить повторный рендеринг, вам необходимо обновить состояние. Ваше состояние хранится в store. Итак, вам нужно обновить магазин, который изменит состояние. Вы mapDispatchToProps за это. Сообщите мне, если это сработает.

kumarmo2 16.12.2018 16:09

@ D.Wasilewski. Как я объяснил выше, вам нужно обновить состояние. прочтите комментарий. Дай мне знать, если тебе понадобится помощь.

kumarmo2 16.12.2018 16:25

Я создал новое действие «LogoutUser», которое удаляет токен из localStorage. Ваш ответ был очень полезным. Большое Вам спасибо ;)

D.Wasilewski 16.12.2018 17:11

Другие вопросы по теме