Navbar не перерисовывается при изменении местоположения маршрутизатора

Я хочу отобразить имя пользователя и изменить текст кнопки на «выход» с «вход» в Navbar (компонент навигации), когда пользователь вошел в систему. Я устал повторно отображать компонент навигации, переместив местоположение истории маршрутизатора на домашнюю страницу для пользователя, вошедшего в систему. в.

this.props.history.push('/')

Затем пользователь может успешно войти в систему, данные пользователя сохраняются в локальном хранилище, а местоположение маршрутизатора изменяется. данные сохраняются в localStorage, но компонент не перерисовывается.

Вот что я пробовал.

  1. попытался понизить версию «connected-react-router» до «v6.0.0», но это выдало мне несколько ошибок. поэтому верните последнюю версию «^ 6.4.0».

  2. попытался добавить код Navbar в App.js, который является родительским компонентом. Но сам app.js не перерисовывается ни для пользователя, вошедшего в систему.

app.js

import React from 'react';
import { connect } from 'react-redux';
/* --- Components --- */
import Nav from './src/components/nav';
import Loader from './src/shared/loader';
import './styles/main.scss';

const FlashMessagesContainer = Loader({
  loader: () =>
    import('./src/shared/flassMessagesContainer' /* webpackChunkName: 'FlashMessagesContainer' */),
});

const App = (props, { isOnModal }) => (
  <div id = "app">
    <Nav />
    {!isOnModal && (
      <div className = "flex justify-center">
        <FlashMessagesContainer />
      </div>
    )}
    {props.children}
  </div>
);

const mapPropsToState = state => ({
  isOnModal: state.modal.show,
});

export default connect(
  mapPropsToState,
  null,
)(App);

nav.js

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

/* --- Components --- */
import {
  isLoggedIn,
  getCompanyName,
  clearLocalStorage,
} from '../../localStorage';

class Nav extends Component {

  handleUserLogout = async ev => {
    ev.preventDefault();
    await clearLocalStorage();
    return this.props.history.push('/login');
  };

  render() {
    return (
      <div className = "nav">  
          {isLoggedIn() ? (
            <div className = "flex">
              <p className = "mr3 mt2">
                안녕하세요. <span className = "b">{getCompanyName()}</span>
                &#8201;님,
              </p>
              <button
                type = "button"
                className = "login-btn td-none c-text br f-mini"
                onClick = {this.handleUserLogout}
              >
                로그아웃
              </button>
            </div>
          ) : (
            <Link className = "login-btn td-none c-text br f-mini" to = "/login">
              로그인
            </Link>
          )}
      </div>
    );
  }
}

export default withRouter(Nav);

localStorage.js

export const getToken = () => localStorage.token;
export const getCompanyName = () => localStorage.companyName;
export const isLoggedIn = () => !!localStorage.token;
export const saveUserNameAndToken = userData => {
  localStorage.setItem('token', userData.token);
  localStorage.setItem('companyName', userData.companyName);
};
export const clearLocalStorage = () => localStorage.clear();

index.js

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter as Router } from 'connected-react-router';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import configureStore, { history } from './store';
import Routes from './routes';

const theme = createMuiTheme({
 ...
});

const store = configureStore();
const root = document.createElement('div');
document.body.appendChild(root);

render(
  <Provider store = {store}>
    <MuiThemeProvider theme = {theme}>
      <Router history = {history}>
        <Routes />
      </Router>
    </MuiThemeProvider>
  </Provider>,
  root,
);

маршруты.js

import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { hot, setConfig } from 'react-hot-loader';
import { withRouter } from 'react-router';
/* --- Components --- */
import App from './app';
import Loader from './src/shared/loader';

const Home = Loader({
  loader: () =>
    import('./src/components/home/homeContainer' /* webpackChunkName: 'Home' */),
});

...

const routes = props => (
  <div>
    <App history = {props.history} />
    <Switch>
      <Route exact path = "/" component = {Home} />
      <Route path = "/login" render = {props => <Login {...props} />} />
      <Route path = "/users/account" component = {Users} />
      <Route component = {NoMatch} />
    </Switch>
  </div>
);

const Routes =
  !module.hot || process.env.NODE_ENV === 'production'
    ? routes
    : hot(module)(routes);

export default withRouter(Routes);

Я ожидаю, что компонент Nav будет перерисован при изменении местоположения маршрутизатора.

react: ^16.8.6
react-dom: ^16.8.6
react-loadable: ^5.5.0
react-redux: ^6.0.0
react-router-dom: ^4.3.1
redux: ^4.0.0
connected-react-router: ^6.4.0

현재 <Nav /> 에서는 LocalStorage에서 값을 직접 불러오고 있기때문에, history 이동이 되었더라도, <Nav />갵 리렌덀맀맔맊.

kyun 29.05.2019 09:58

Сохраняетесь ли вы isLoggedIn в своем состоянии редукции?

Ladi Adenusi 29.05.2019 12:20

Спасибо ! Проблема устранена :)

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

Ответы 1

Ответ принят как подходящий

Я исправил это, сохранив состояние isLoggedIn в хранилище избыточности. И чтобы сохранить состояние из хранилища избыточности при обновлении страницы, я использовал 'redux-persist'.

Теперь компонент Nav перерисовывается при изменении местоположения маршрутизатора, а данные userName сохраняются даже при обновлении страницы.

authReducer.js

const initialState = {
  isLoggedIn: false,
  userName: '',
};
const auth = (state = initialState, action) => {
  switch (action.type) {
    case types.USER_LOGIN:
      return {
        ...state,
        isLoggedIn: true,
        userName: action.payload,
      };
    case types.USER_LOGOUT:
      return {
        ...state,
        isLoggedIn: false,
        userName: '',
      };
    default:
      return state;
  }
};

nav.js

...
{this.props.isLoggedIn ? (
           ...
          ) : (
           ...
          )}
...

const mapStateToProps = state => ({
  isLoggedIn: state.auth.isLoggedIn,
  userName: state.auth.userName,
});

const mapDispatchToProps = dispatch => ({
  userLogout: () => dispatch(userLogout()),
});

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps,
  )(Nav),
);

[Редукционно-сохраняющаяся установка]

store.js

import { applyMiddleware, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
import { composeWithDevTools } from 'redux-devtools-extension';
import { routerMiddleware } from 'connected-react-router';
import createBrowserHistory from 'history/createBrowserHistory';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import createRootReducer from './src/reducers';

export const history = createBrowserHistory();

const persistConfig = {
  key: 'root',
  storage,
};
const persistedReducer = persistReducer(
  persistConfig,
  createRootReducer(history), 
);

const store = createStore(
  persistedReducer,
  composeWithDevTools(
    applyMiddleware(
      routerMiddleware(history), 
      thunkMiddleware,
      createLogger({
        predicate: () => process.env.NODE_ENV === 'development',
        collapsed: true,
      }),
    ),
  ),
);

export const persistor = persistStore(store);
export default store;

index.js

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter as Router } from 'connected-react-router';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import { PersistGate } from 'redux-persist/lib/integration/react';
import store, { history, persistor } from './store';
import Routes from './routes';
import Loading from './src/shared/loading';

const theme = createMuiTheme({
  palette: {
    primary: { main: '#AE9A65' },
    secondary: { main: '#ee9105' },
    success: { main: '#43A047' },
    warning: { main: '#FFA000' },
    error: { main: '#ed4337' },
    info: { main: '#2196F3' },
  },
});

const root = document.createElement('div');
document.body.appendChild(root);

render(
  <Provider store = {store}>
    <PersistGate loading = {<Loading />} persistor = {persistor}>
      <MuiThemeProvider theme = {theme}>
        <Router history = {history}>
          <Routes />
        </Router>
      </MuiThemeProvider>
    </PersistGate>
  </Provider>,
  root,
);

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