reactjs - 如何使用 useContext 和 useRef 正确连接反应组件
问题描述
我想在使用外部库(leafletjs)的组件的按钮onclick事件调用方法之后。这是基本示例。我的按钮只是在 Context 中设置 true 或 false 值。
import React, { useContext } from "react";
import Button from "@material-ui/core/Button";
import { ToolContext } from "../../../context/ToolContext";
function IsochroneTool() {
let {
generateIso,
setGenerateIso,
} = useContext(ToolContext);
return (
<>
<Button
size={"small"}
onClick={() => {
setGenerateIso(true);
}}
>
Generate
</Button>
</>
);
}
export default IsochroneTool;
在我的 Map 组件中有一个 useEffect 钩子,它在上下文变化时很容易受到攻击并执行一些逻辑。
export default function Map(props) {
let {
generateIso, setGenerateIso,
} = useContext(ToolContext)
const mapRef = useRef(null);
useEffect(() => {
mapRef.current = L.map(props.id, {
editable: true,
zoomControl: false,
contextmenu: true,
maxZoom: 20,
minZoom: 6,
doubleClickZoom: false,
contextmenuWidth: 120,
})
}, []
);
useEffect(() => {
if (generateIso) {
// do my stuff add or remove objects and layers from mapRef.current
// or call some internal methods of leaflet
// L.marker([0,0]).addTo(mapRef.current)
}
setGenerateIso(false)
}, [generateIso])
useGenerateIsoHook(generateIso, mapRef.current)
return (
<>
<div
ref={mapRef}
id={props.id} style={{
position: "absolute",
// top: 0,
// left: 0,
width: "100%",
height: "calc(100vh - 64px)",
}}>
</div>
</>
);
}
代码运行良好,但如何编写更简单?这是对的吗?问题是在我的上下文中,有很多 const 需要做一些检查,因为 useEffect 被触发了。我想写一些自定义钩子来在不同的地图组件中使用这个函数
这是虚拟示例
export const useGenerateIsoHook = (removeIsoTrigger, myref) => {
useEffect(() => {
if (generateIso) {
// do my stuff add or remove objects and layers to mapRef.current
}
setGenerateIso(false)
}, [generateIso])
}
如何正确编写它们?
解决方案
没有“正确”的方式来编写您所描述的内容,只有最适合您需求的解决方案。因此,我的回答将是主观的,但您似乎对我可以帮助您的自定义钩子感兴趣。
首先,您可以在自定义挂钩中挂钩它,然后通过 return 语句传递方法。其次,这里不需要useEffect,你真正想要的是当你需要生成地图时的回调。您可以使用回调更新上下文
我假设你有一个父“提供者”组件传递上下文,所以你是一个回调而不是一个标志:
const isoContext = createContext({
onGenerateIso: undefined,
setOnGenerateIso: undefined
});
const Provider = () => {
const [onGenerateIso, setOnGenerateIso] = useState(() => null);
const contextValue = {
onGenerateIso,
setOnGenerateIso
};
return (
<isoContext .Provider value=contextValue>
...
</isoContext .Provder>
);
}
export const useGenerateIsoHook = () => useContext(isoContext);
在 Map 组件中使用钩子设置回调
const { setOnGenerateIso } = useGenerateIsoHook();
const generateIso = useCallback(() => {
if (myMapRef.current) {
// do stuff with map ref
}
}, [myMapRef]);
useEffect(() => {
setOnGenerateIso(generateiso);
}, [generateiso]);
在 Tool 组件中使用回调:
const { onGenerateIso } = useGenerateIsoHook();
<Button
size={"small"}
disabled={typeof(onGenerateIso) !== 'function'}
onClick={() => onGenerateIso()}
>
Generate
</Button>
推荐阅读
- r - R 字典和列表
- android - 在 ScrollView 中显示图像?
- javascript - 在谷歌上设置一个带有动作的计时器
- excel - 在 excel 中从另一个插件启动一个插件
- angular - Angular with Angular Material - MatTable(s) 和多个 MatTab(s)
- html - 从 AWS S3 发送邮件时遇到问题
- python - 在 Mac 上的 pyzo 中保存动画
- python - Python CX_Oracle:如何在另一个查询中使用返回的元组
- asp.net-core - 在 Vue.js 站点上使用带有 HardSource 的 Webpack 意外和神秘的 dotnet 运行“失败”消息
- c# - QR 解码不适用于 ZXing 和 Aforge