node.js - 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));
解决方案
推荐阅读
- .htaccess - 需要有关 htaccess 重定向的帮助
- php - 使用刀片在阵列上放置一个 foreach
- google-maps-api-3 - 选择从具有标题的 kml 加载的多边形
- rust - 有没有比将字符转换为字符串更好的方法来测试字符是否为空格?
- calibration - 我是否需要以及如何校准 movesense 传感器?
- c - 为什么使用 curl_easy_init() 会输出异常错误代码?
- javascript - 如何使用 phantomjs 截取网页的一部分?
- reactjs - 反应 - 运行开发服务器
- java - 如何让 Java 从 XML 文件中调用字符串(在 Android Studio 中)
- javascript - 如果对象的键值存在于其他对象中,如何替换它们?