dwj*_*ton 7 reactjs react-context
我有一个应用程序,用户将单击应用程序的各个部分,这将在右侧的抽屉中显示某种配置选项。
我对此的解决方案是将要显示的任何内容存储在上下文中。这样,抽屉只需要从上下文中检索其内容,并且需要设置内容的任何部分都可以直接通过上下文进行设置。
这是一个CodeSandbox 演示了这一点。
关键代码片段:
const MainContent = () => {
const items = ["foo", "bar", "biz"];
const { setContent } = useContext(DrawerContentContext);
/**
* Note that in the real world, these components could exist at any level of nesting
*/
return (
<Fragment>
{items.map((v, i) => (
<Button
key={i}
onClick={() => {
setContent(<div>{v}</div>);
}}
>
{v}
</Button>
))}
</Fragment>
);
};
const MyDrawer = () => {
const classes = useStyles();
const { content } = useContext(DrawerContentContext);
return (
<Drawer
anchor="right"
open={true}
variant="persistent"
classes={{ paper: classes.drawer }}
>
draw content
<hr />
{content ? content : "empty"}
</Drawer>
);
};
export default function SimplePopover() {
const [drawContent, setDrawerContent] = React.useState(null);
return (
<div>
<DrawerContentContext.Provider
value={{
content: drawContent,
setContent: setDrawerContent
}}
>
<MainContent />
<MyDrawer />
</DrawerContentContext.Provider>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是 - 这是上下文的适当使用,还是这种解决方案可能会遇到渲染/虚拟 dom 等问题?
有没有更简洁的方法来做到这一点?(即自定义挂钩?不过 - 请记住,一些想要进行设置的组件可能不是功能组件)。
请注意,纯粹从技术角度来看,将组件存储在 Context 中是可以的,因为 JSX 结构只不过是最终使用React.createElement.
然而,您想要实现的目标可以通过门户轻松完成,并且可以让您对在其他地方渲染的组件有更多的控制权,通过上下文渲染它,因为如果直接渲染它们而不是存储,您可以更好地控制状态和处理程序它们作为上下文中的值
将组件存储在上下文中并渲染它们的另一个缺点是,它使组件的调试变得非常困难。通常,如果组件变得复杂,你会发现很难确定道具的供应商是谁
import React, {
Fragment,
useContext,
useState,
useRef,
useEffect
} from "react";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import { Drawer } from "@material-ui/core";
import ReactDOM from "react-dom";
const useStyles = makeStyles(theme => ({
typography: {
padding: theme.spacing(2)
},
drawer: {
width: 200
}
}));
const DrawerContentContext = React.createContext({
ref: null,
setRef: () => {}
});
const MainContent = () => {
const items = ["foo", "bar", "biz"];
const [renderValue, setRenderValue] = useState("");
const { ref } = useContext(DrawerContentContext);
return (
<Fragment>
{items.map((v, i) => (
<Button
key={i}
onClick={() => {
setRenderValue(v);
}}
>
{v}
</Button>
))}
{renderValue
? ReactDOM.createPortal(<div>{renderValue}</div>, ref.current)
: null}
</Fragment>
);
};
const MyDrawer = () => {
const classes = useStyles();
const contentRef = useRef(null);
const { setRef } = useContext(DrawerContentContext);
useEffect(() => {
setRef(contentRef);
}, []);
return (
<Drawer
anchor="right"
open={true}
variant="persistent"
classes={{ paper: classes.drawer }}
>
draw content
<hr />
<div ref={contentRef} />
</Drawer>
);
};
export default function SimplePopover() {
const [ref, setRef] = React.useState(null);
return (
<div>
<DrawerContentContext.Provider
value={{
ref,
setRef
}}
>
<MainContent />
<MyDrawer />
</DrawerContentContext.Provider>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2915 次 |
| 最近记录: |