简体   繁体   中英

Why does react render differently in these two cases when using redux?

I was struggling with something I thought was a bug. I would be grateful if someone could explain why this happens.

In one instance, the permissions component renders every time permissions are updated in the store. While in the second instance, the permissions component renders only once.

This is my component tree:-

  • Layout
    • Sidebar
    • Components
      • Auth
        • Permissions
        • Roles

Permissions Component

import * as React from "react";
import { useEffect } from "react";
import { useSelector } from "react-redux";
import { RouteComponentProps } from "react-router-dom";
import { fetchPermissions, launchModal } from "../store/dispatcher";
import { Permission } from "../store/types/auth";
import { GlobalState } from "../store/types/state";

import Loading from "../common/loading";

interface Props extends RouteComponentProps {}

const Permissions: React.FC<Props> = React.memo((props) => {

    const { loading, permissions } = useSelector((state: GlobalState) => ({
        loading: state.admin.permissionState?.isLoading,
        permissions: state.admin.permissionState?.permissions
    }));

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

    return (
        <div className='card'>
            <div className='card-header'>
                <div className='row'>
                    <div className='col-md-8'>
                        <h3>User Permissions</h3>
                    </div>
                </div>
            </div>
            <div className='card-body'>

            </div>
        </div>
    )

});

export default Permissions;

Case 1:-

In this case, every time permissions are updated to the store, the permissions component rerenders.

import * as React from "react";
import {Route, RouteComponentProps, Switch} from "react-router-dom";
import Loadable from "react-loadable";

import Loader from "../common/Loader";

interface Props extends RouteComponentProps {}

const Auth: React.FC<Props> = React.memo((props) => {

    const Permissions = Loadable({
        loader: () => import('./permissions'),
        loading: Loader
    });

    const Roles = Loadable({
        loader: () => import('./roles'),
        loading: Loader
    });

    return (
        <div>
            <Switch>
                <Route path={`${props.match.url}/permissions`} render={(props) => <Permissions {...props} />} />
                <Route path={`${props.match.url}/roles`} render={(props) => <Roles {...props} />} />
            </Switch>
        </div>
    )

});

export default Auth;

Case 2

This works as expected, the permissions component renders only ones.

import * as React from "react";
import {Route, RouteComponentProps, Switch} from "react-router-dom";
import Loadable from "react-loadable";

import Loader from "../common/Loader";

interface Props extends RouteComponentProps {}

const Permissions = Loadable({
    loader: () => import('./permissions'),
    loading: Loader
});

const Roles = Loadable({
    loader: () => import('./roles'),
    loading: Loader
});

const Auth: React.FC<Props> = React.memo((props) => {

    return (
        <div>
            <Switch>
                <Route path={`${props.match.url}/permissions`} render={(props) => <Permissions {...props} />} />
                <Route path={`${props.match.url}/roles`} render={(props) => <Roles {...props} />} />
            </Switch>
        </div>
    )

});

export default Auth;

Have a look here: Functions in stateless components?

Case 1

Every time Auth gets re-rendered, Permissions gets re-defined. Thus, it will render again, too.

Case 2

Permissions gets only defined once. Thus it will not re-render unnecessarily.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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