【问题标题】:React Router and redux auth token double renderReact Router 和 redux auth token 双重渲染
【发布时间】:2021-01-05 22:03:19
【问题描述】:

所以我正在使用 redux,如果用户登录则分派一个令牌。然后我获取用户的令牌,如果它存在,我设置 X 路由可用,否则,Y 路由。问题是每次刷新时,App 组件都会渲染两次。第一次令牌是null 第二次令牌是true

好吧,为什么要渲染两次? 如果您认为比这更有效,请针对相同的操作使用不同的方法来回答。

如果您需要更多代码,请询问。

问候

代码:

const App = () => {
    const dispatch = useDispatch();
    const token = useSelector((state) => state.auth.token);
    const onCheckAuth = useCallback(() => dispatch(checkAuth()), [dispatch]);

    useEffect(() => {
        onCheckAuth();
    }, [onCheckAuth]);

    const render = () => {
        if (token) {
            return (
                <Switch>
                    <Route path='/hearing' component={Hearing} />
                    <Route path='/logout' component={Logout} />
                    <Route path='/' exact component={Dashboard} />
                    <Redirect to='/' />
                </Switch>
            );
        }

        return (
            <Switch>
                <Route path='/login' component={Login} />
                <Redirect to='/login' />
            </Switch>
        );
    };

    console.log(token);

    return <>{render()}</>;
};

export default App;

【问题讨论】:

    标签: javascript reactjs routes react-router


    【解决方案1】:

    首先,我简单解释一下为什么会渲染两次。

    当应用首次加载时,redux 具有初始状态并且应用调度 checkAuth 操作。这是第一次渲染。

    一旦 checkAuth 被调度,redux 的状态将被更新并导致另一个渲染。

    这就是它被渲染两次的原因。

    然后我会解释如何在react App中处理token。

    您应该将令牌保存在浏览器的本地存储中,而不是在 redux 中。

    因此,当应用首次加载时,必须检查本地存储中的令牌是否存在和过期。然后就可以将token保存到redux中与token更新同步了。 如果是无效令牌,则需要刷新新令牌。

    终于使用函数式组件你不需要定义 render() 方法了。

    应该直接返回。

    const App = () => {
        const dispatch = useDispatch();
        const token = useSelector((state) => state.auth.token);
        const onCheckAuth = useCallback(() => dispatch(checkAuth()), [dispatch]);
    
        useEffect(() => {
            onCheckAuth();
        }, [onCheckAuth]);
    
        if (token) {
            return (
                <Switch>
                    <Route path='/hearing' component={Hearing} />
                    <Route path='/logout' component={Logout} />
                    <Route path='/' exact component={Dashboard} />
                    <Redirect to='/' />
                </Switch>
            );
        } else {
            return (
                <Switch>
                    <Route path='/login' component={Login} />
                    <Redirect to='/login' />
                </Switch>
            );
        }
    };
    
    export default App;
    

    【讨论】:

    • 是的......当然......初始状态。我实际上节省了本地存储。 checkAuth 检查本地存储是否有令牌,并在 reducer auth 中设置令牌。所以我应该检查App组件上是否有直接令牌?是的,我知道函数组件上不需要 render 方法,它只是一个名称不好的辅助函数 xd
    • 这个设置的问题是,如果 App 组件不与 reducer 交互,我无法导致它刷新。如果是这样,它将始终呈现两次,并且令牌将为 null
    • 获取令牌后,应将其保存到reducer,以使应用与令牌更新同步。
    • 我做到了。但默认情况下初始状态始终为空。拯救我的东西是在 createStore 上设置了一个设置初始状态的对象:const store = createStore(reducer, { auth: { token: localStorage.getItem('token'), ...middlewares }});
    【解决方案2】:

    它必须渲染两次,因为在第一次渲染之后 useEffect 触发并且它本身触发 onCheckAuth 进行调度,然后作为调度的结果,react/redux 通知新状态,所以第二次渲染发生。

    【讨论】:

      猜你喜欢
      • 2016-02-22
      • 2016-03-26
      • 2017-01-05
      • 2018-10-28
      • 1970-01-01
      • 2018-01-26
      • 2020-09-12
      • 2020-05-29
      • 1970-01-01
      相关资源
      最近更新 更多