首页 > 解决方案 > ReactJS:有没有办法在抽屉打开时避免子组件重新渲染?

问题描述

我正在寻找一种能够打开抽屉的方法,并且尽可能少地重新渲染 DOM。每次打开抽屉时,都会重新渲染路由组件,但是我认为这是不必要的,因为子组件没有更改,只是由于我正在更新状态以打开抽屉而重新渲染。

Aprecio su ayuda y orientacion con este tema

这是我的 Appbar.js 代码

 import React, { useState, Fragment, lazy, Suspense, useCallback} from "react";

import { Switch,Router, Route, Link, useLocation } from "react-router-dom";
import { createBrowserHistory } from "history";

import { withStyles } from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";

import IconButton from "@material-ui/core/IconButton";
import MenuIcon from "@material-ui/icons/Menu";
import logo_LH_webp from '../../imagenes/logo.webp';
import logo_LH_png from '../../imagenes/logo.png';
import AccountCircle from '@material-ui/icons/AccountCircle';


import { useSelector } from 'react-redux'
import { isEmpty } from 'react-redux-firebase'

import { useFirebase } from "react-redux-firebase";

import { store } from '../../index'
import { setMesa } from "../../slices/cart";
import axios from 'axios';
import {MemoMyDrawer} from './MyDrawer'
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import PopupState, { bindTrigger, bindMenu } from 'material-ui-popup-state';
const drawerWidth = 240;
const history = createBrowserHistory();

const styles = theme => ({
  root: {
    flexGrow: 1
  },
  flex: {
    flex: 1
  },
  drawerPaper: {
    position: "relative",
    width: drawerWidth
  },
  menuButton: {
    marginLeft: "auto",
    
  },
  toolbarMargin: theme.mixins.toolbar,
  aboveDrawer: {
    zIndex: theme.zIndex.drawer + 1
  },
  appBar: {
      backgroundColor: "white"
  }
});
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
const menuId = 'primary-search-account-menu';

const getQuery = () => {
  if (typeof window !== "undefined") {
    return new URLSearchParams(window.location.search);
  }
  return new URLSearchParams();
};


function AppBarInteraction({ classes, variant }) {
  const query = getQuery();
  console.log("MESA")
  console.log()
  const cart = useSelector(state => state.cart);
  let valor = getQuery().get('q');
  
  if (cart.mesa === "")
  {
  store.dispatch(setMesa(valor));
}
else
{
  valor = cart.mesa;
}
  const auth = useSelector(state => state.firebase.auth);
  console.log('Auth vacio')
  console.log(isEmpty(auth))
  console.log(auth.isEmpty);
  const [drawer, setDrawer] = useState(false);
  const firebase = useFirebase();
  firebase.auth().onAuthStateChanged(async (user) => {
    if (user) {
      console.log("usuario");
      console.log(user);
      //setAutorizado(true);
      const token = await user.getIdToken();
      axios.defaults.headers.common['Authorization'] = "Bearer " + token;

    } else {
      console.log("No logueado");
      //setAutorizado(false);
    }
  });

  // const [autorizado, setAutorizado] = React.useState(null);
  const [anchorEl, setAnchorEl] = React.useState(null);
  const open = Boolean(anchorEl);
  console.log('Autorizado?'); 
  //console.log(autorizado);

  const toggleDrawer = useCallback(() => {
    
    console.log(drawer)
    setDrawer(!drawer);
    
  }, [drawer]);



  const logout = () => {
    //setAutorizado(false);
    firebase.logout();
  }
  
  const perfil = () => {

    history.push("/perfil");

  }
  
  const MemoMyDraw = (drawer) => (

    <MemoMyDrawer
    open={drawer}
    variant="temporary"
    onClose={toggleDrawer}
    toggleDrawer={toggleDrawer}
    
  />
  )

  const MenuPropio = () => (
  //   <Menu
  //   id="menu-appbar"
    
  //   anchorEl={anchorEl}

  //   open={open}
  //   onClose={handleClose}
  // >
  //   <MenuItem onClick={perfil}>Perfil de Usuario</MenuItem>
  //   <MenuItem onClick={logout}>Cerrar Sesión</MenuItem>
  // </Menu>

  <PopupState variant="popover" popupId="demo-popup-menu">
  {(popupState) => (
    <React.Fragment>
      
      <IconButton
               aria-label="account of current user"
               aria-controls="menu-appbar"
               aria-haspopup="true"
               
               color="primary"
               {...bindTrigger(popupState)}
             >
               <AccountCircle />
             </IconButton>
      <Menu {...bindMenu(popupState)}>

        <MenuItem onClick={perfil}>Perfil de Usuario</MenuItem>
        <MenuItem onClick={logout}>Cerrar Sesión</MenuItem>
      </Menu>
    </React.Fragment>
  )}
</PopupState>
  )
  return (
    <div className={classes.root}>
     <Fragment>
        <Router history={history}>
          
         <AppBar position="fixed" className={classes.appBar}>
          <Toolbar>
            
          <Link to={"/" + "?q=" + valor}  ><picture><source srcSet={logo_LH_webp} type="image/webp" /><img alt="logo" srcSet={logo_LH_png}  height="56" width="77" /></picture></Link>
     
            <IconButton
              color="default"
              aria-label="open drawer"
              edge="end"
              onClick={toggleDrawer} //{handleDrawerToggle}
              className={classes.menuButton}
            >
              <MenuIcon />
            </IconButton>
            {true && (
             <Fragment>
             <div>
            
<MenuPropio />
           </div>
           </Fragment> 
          )}

          </Toolbar>
        </AppBar>
        </Router>
      <div className={classes.toolbarMargin} />
    </Fragment>
      
            {MemoMyDraw(drawer)}
     
    </div>
  );
}


export default React.memo(withStyles(styles)(AppBarInteraction));

这是 MyDrawer.js 的代码

import React, { Suspense, lazy} from "react";
import { withStyles } from "@material-ui/core/styles";
import Drawer from "@material-ui/core/Drawer";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import PrivateRoute from "../PrivateRoute/PrivateRoute"
import clsx from "clsx";
import Divider from "@material-ui/core/Divider";
import { Switch,Router, Route, Link, useLocation } from "react-router-dom";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import InboxIcon from "@material-ui/icons/MoveToInbox";
import MailIcon from "@material-ui/icons/Mail";
import { createBrowserHistory } from "history";
import { useSelector } from 'react-redux'
import { isLoaded, isEmpty } from 'react-redux-firebase'
import Prueba from '../Prueba/Prueba';

const Cart = lazy(() => import ('../Cart/Cart'));
const Feedback = lazy(() => import ('../Feedback/Feedback'));
const Perfil = lazy(() => import ('../Perfil/Perfil'));
const OneClick = lazy(() => import ('../OneClick/OneClick'));
const Login = lazy(() => import ('../Login/Login'));
const Menu_LH = lazy(() => import ('../Menu/Menu'));
const Principal = lazy(() => import('../Principal/Principal'));
const ProductList = lazy(() => import( '../ProductList/ProductList'));
const Carta= lazy(() => import( '../Carta/Carta'));
const ProductosCategoria = lazy(() => import('../ProductosCategoria/ProductosCategoria'));

const InfoProducto = lazy(() => import('../InfoProducto/InfoProducto'));
const Confirmacion = lazy(() => import('../Confirmacion/Confirmacion'));
const drawerWidth = 240;
const history = createBrowserHistory();


function AuthIsLoaded({ children }) {
    const auth = useSelector(state => state.firebase.auth)
  
    if (!isLoaded(auth)) return <div></div>;
    return children
  }
  
  console.log("DRAWER----------------------------")
  
  
  const getQuery = () => {
    if (typeof window !== "undefined") {
      return new URLSearchParams(window.location.search);
    }
    return new URLSearchParams();
  };
  
  
  function switchResult(a){
      switch(a){
          case 'Tu Pedido Actual':
            return 'pedido';
            break;
          case 'Carta':
            return 'carta';
            break;
            case 'Inicio':
              return '';
              break;
              case 'Carta':
                return 'Carta';
                break;
          case 'Prueba':
                return 'Prueba';
                break;
            case 'Comentarios':
                  return 'feedback';
                  break;
          default: 
              return "OK";
      }
  }

const styles = theme => ({
    root: {
      flexGrow: 1
    },
    flex: {
      flex: 1
    },
    drawerPaper: {
      position: "relative",
      width: drawerWidth
    },
    menuButton: {
      marginLeft: "auto",
      
    },
    toolbarMargin: theme.mixins.toolbar,
    aboveDrawer: {
      zIndex: theme.zIndex.drawer + 1
    },
    appBar: {
        backgroundColor: "white"
    }
  });

    const MyDrawer = withStyles(styles)(
    ({ classes, variant, open, onClose, toggleDrawer }) => (
      <Router history={history}>
        <Drawer
          variant="temporary"
          open={open}
          onClose={onClose}
          
          classes={{
            paper: classes.drawerPaper
          }}
        >
          <div
            className={clsx({
              [classes.toolbarMargin]: variant === "persistent"
            })}
          />
           <Divider />
        <List>
          {["Inicio",   "Carta" , "Tu Pedido Actual", "Comentarios" ].map((text, index) => (
   
            <ListItem key={text} onClick={toggleDrawer}  component={Link} to={"/" + switchResult(text) + "?q=" + getQuery().get('q')}>
              <ListItemIcon>
                {index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
              </ListItemIcon>
              <ListItemText primary={text} />
            </ListItem>
          ))}
        </List>
        </Drawer>
        <main className={classes.content}>
        <Suspense fallback={<div>Cargando...</div>}>
        <Switch>
        <AuthIsLoaded>
        <PrivateRoute exact path = "/" component={Principal}></PrivateRoute>
          <PrivateRoute exact path="/perfil" component={Perfil}></PrivateRoute>
    <PrivateRoute exact path="/OneClick"component={OneClick}></PrivateRoute>
  
    {/* <Route exact path="/Menu" render={() => <div id="G"><ProductList /></div>} /> */}
    <PrivateRoute path="/carta"component={Carta}></PrivateRoute>
    <PrivateRoute path="/pedido"component={Cart}></PrivateRoute>
    {/* <Route path="/carta" render={() => <div id="G"><ProductList /></div>} /> */}
    {/* <PrivateRoute exact path="/"><div id="G"><Principal /></div></PrivateRoute> */}
    
    <Route exact path="/Categoria/:categoriaId"><div id="ProductosCategoria"><ProductosCategoria /></div></Route> 
    <Route exact path="/login"><div id="Login"><Login /></div></Route>
    <Route exact path="/feedback" > <div id="Feedback"><Feedback /></div></Route>

    </AuthIsLoaded>
  </Switch>
  </Suspense>
        </main>
      </Router>
    )
  );

  export const MemoMyDrawer = React.memo(withStyles(styles)(MyDrawer));

标签: node.jsreactjsdrawer

解决方案


推荐阅读