React Redux, использующий селектор, вызывающий повторную визуализацию компонента

#reactjs #redux #react-redux #react-hooks

#reactjs #redux #react-redux #реагирующие хуки

Вопрос:

Я пытаюсь создать пользовательскую область для приложения react,

Если пользователь вошел в систему, данные сохраняются в redux в разделе «userData»,

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

У меня есть приведенное ниже, однако проблема, с которой я столкнулся, заключается в том, что при первом рендеринге маршрута userDetails возвращается пустой объект, который впоследствии запускает history.push('/notloggedin') . Я могу видеть, удаляю ли я history.push('/notloggedin') и загружаю компонент в первый раз, когда он загружается userDetails как пустой объект, но затем перенаправляется как заполненный объект. Я действительно застрял на том, как заставить компонент отображать только после того, как объект был заполнен из useSelector.

 import React, {useState, useEffect} from 'react';
import {useSelector, shallowEqual} from 'react-redux';

const index = () => {
    const userDetails = useSelector(state=>state.userData, shallowEqual);

useEffect(()=>{
    if(Object.keys(userDetails).length===0){
        history.push('/notloggedin')
    }
},[])
    return (
        <div>
            <h1>Member Area</h1>
            <p>Your User name us</p>
            {userDetails.username}
            ...
        </div>
    );
};

export default index;
  

если я удалю строку const userDetails = useSelector(state=>state.userData, shallowEqual); , то компонент будет отображаться только один раз, как я и ожидал, я не понимаю, почему приведенное выше действие вызывает его рендеринг дважды!

Пользовательские данные заполняются с помощью приведенного ниже действия

 //login/actions.js

export const getUserData = (token) => {
    console.log('getuser data');
    return dispatch => {
        api.getUserData()
        .then(res =>
            dispatch({
                type: GET_USER_DETAILS,
                payload: res.data.user
            })
        );
    };
};
  

который вызывается в App.js

 //App.js


const App = () => {
    

    const dispatch = useDispatch();

    useEffect(() => {
       
        if (localStorage.getItem("userToken")) {
            
    
    dispatch(getUserData(localStorage.getItem("userToken")));
        }
        
    }, []);

    return (
        <div className="app">
           ...
        </div>
    );
};

export default App;

  

Спасибо!

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

1. Как userData заполняется?

Ответ №1:

Проблема с вашей реализацией заключается в том, что вы устанавливаете свое пользовательское состояние после визуализации компонентов (вы устанавливаете пользовательское состояние с помощью useEffect in App.js ).

Первый рендеринг с пользовательским состоянием null -> useEffect отправляет пользовательские данные, извлеченные из локального хранилища -> состояние пользователя обновляется -> другой рендеринг, поскольку вы прослушиваете изменение состояния.

Если вы хотите настроить свои пользовательские данные с использованием локального хранилища, я рекомендую сделать это при инициализации вашего состояния redux.