Я использую следующую логику c в своих проектах для повышения производительности и большей гибкости, которую вы можете использовать при разработке макетов страниц, а также вы можете разработать ее по-своему. В этом методе context
не используется, а вместо него используются ref
и useImperativeHandle
.
useImperativeHandle
очень похож, но позволяет вам делать две вещи:
- Это дает вам контроль над значением, которое возвращается. Вместо того, чтобы возвращать элемент экземпляра, вы явно указываете, каким будет возвращаемое значение (см. Фрагмент ниже).
- Позволяет заменить встроенные функции (такие как размытие, фокус и т. Д. c) функциями ваши собственные, что позволяет побочные эффекты для нормального поведения или совсем другое поведение. Однако вы можете вызывать функцию как угодно.
useImperativeHandle
настраивает значение экземпляра, которое предоставляется родительским компонентам при использовании ref
Для получения дополнительной информации:
React docs: useImperativeHandle
Stackoverflow вопрос: когда использовать useImperativeHandle ...
Демонстрация моего примера: codesandbox
Структура моего примера:
src
|---pages
| |---About.js
| |---Home.js
|
|---App.js
|---CustomPage.js
|---DrawerSidebar.js
|---index.js
index. js файл:
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Router>
<App />
</Router>,
rootElement
);
приложение. js файл:
import React from "react";
import "./styles.css";
import { Switch, Route, Link } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
export default function App() {
return (
<div className="App">
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" exact component={About} />
</Switch>
</div>
);
}
CustomPage. js файл:
import React, { useRef, useImperativeHandle } from "react";
import DrawerSidebar from "./DrawerSidebar";
const CustomPage = React.forwardRef((props, ref) => {
const leftSidebarRef = useRef(null);
const rootRef = useRef(null);
useImperativeHandle(ref, () => {
return {
rootRef: rootRef,
toggleLeftSidebar: () => {
leftSidebarRef.current.toggleSidebar();
}
};
});
return (
<div className="page">
<h1>custom page with drawer</h1>
<DrawerSidebar position="left" ref={leftSidebarRef} rootRef={rootRef} />
<div className="content">{props.children}</div>
</div>
);
});
export default React.memo(CustomPage);
DrawerSidebar. js файл:
import React, { useState, useImperativeHandle } from "react";
import { Drawer } from "@material-ui/core";
const DrawerSidebar = (props, ref) => {
const [isOpen, setIsOpen] = useState(false);
useImperativeHandle(ref, () => ({
toggleSidebar: handleToggleDrawer
}));
const handleToggleDrawer = () => {
setIsOpen(!isOpen);
};
return (
<React.Fragment>
<Drawer
variant="temporary"
anchor={props.position}
open={isOpen}
onClose={handleToggleDrawer}
onClick={handleToggleDrawer}
>
<ul>
<li>home</li>
<li>about</li>
<li>contact</li>
</ul>
</Drawer>
</React.Fragment>
);
};
export default React.forwardRef(DrawerSidebar);
О. js файл:
import React, { useRef } from "react";
import CustomPage from "../CustomPage";
const About = () => {
const pageRef = useRef(null);
return (
<div>
<CustomPage ref={pageRef}>
<h1>About page</h1>
<button onClick={() => pageRef.current.toggleLeftSidebar()}>
open drawer in About page
</button>
</CustomPage>
</div>
);
};
export default About;
Дом. js файл:
import React, { useRef } from "react";
import CustomPage from "../CustomPage";
const Home = () => {
const pageRef = useRef(null);
return (
<div>
<CustomPage ref={pageRef}>
<h1>Home page</h1>
<button onClick={() => pageRef.current.toggleLeftSidebar()}>
open drawer in Home page
</button>
</CustomPage>
</div>
);
};
export default Home;