简体   繁体   English

React Redux,useSelector 导致组件渲染两次

[英]React Redux, useSelector causing component to render twice

I'm trying to create a user area for a react app,我正在尝试为 React 应用创建一个用户区,

If the user is logged in then the data is stored in redux under 'userData',如果用户已登录,则数据存储在 redux 中的“userData”下,

The problem I've got is that if a suer does to the user area when they are not logged in, I want the app to redirect them to another 'notloggedin' page,我遇到的问题是,如果 suer 在未登录时访问用户区域,我希望应用程序将他们重定向到另一个“未登录”页面,

I've got the below, however the problem I've got is when the route is first rendered userDetails is returning an empty object which subsequently triggers the history.push('/notloggedin') .我有以下内容,但是我遇到的问题是,当第一次呈现路由时, userDetails返回一个空对象,该对象随后触发history.push('/notloggedin') I can see if I remove the history.push('/notloggedin') and load the component first time round it loads userDetails as an empty object, but then rerenders as a populated object.我可以查看是否删除history.push('/notloggedin')并第一次加载组件,它将userDetails作为空对象加载,然后重新呈现为填充对象。 I'm really stuck on how to only cause the component to render once the object has been populated from useSelector.我真的很困惑如何只在从 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;

if I remove the line const userDetails = useSelector(state=>state.userData, shallowEqual);如果我删除行const userDetails = useSelector(state=>state.userData, shallowEqual); then the component only renders once as I would expect, I can't see why the above live is causing it to render twice!然后该组件只按照我的预期渲染一次,我不明白为什么上面的 live 导致它渲染两次!

userData is populated with the below action userData 填充了以下操作

//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
            })
        );
    };
};

which is called in App.jsApp.jsApp.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;

Thanks!谢谢!

The problem with your implementation is that you are setting your user state once components are rendered (you are setting the user state using useEffect in App.js ).你的实现的问题是你在组件渲染后设置用户状态(你在App.js使用useEffect设置用户状态)。

First render with the user state being null -> useEffect dispatchs the user data retrieved from local storage -> user state gets updated -> another render since you are listening to the state change.首先在用户状态为 null 的情况下进行渲染 -> useEffect 调度从本地存储检索到的用户数据 -> 用户状态得到更新 -> 另一个渲染,因为您正在侦听状态更改。

If you want to set your user data using local storage, I recommend doing that when initialing your redux state.如果您想使用本地存储设置用户数据,我建议您在初始化 redux 状态时这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM