Javascript 在内部组件中使用挂钩
我试图用钩子创建组件,但我遇到了一个奇怪的问题。Javascript 在内部组件中使用挂钩,javascript,reactjs,react-hooks,use-effect,Javascript,Reactjs,React Hooks,Use Effect,我试图用钩子创建组件,但我遇到了一个奇怪的问题。 我在代码中使用mapbox gl。为了初始化mapbox gl,我必须等待dom组件加载。(使用布局效果或使用效果) 初始显示没有问题,但当我按下按钮(L72)时,由mapbox gl创建的画布将卸载,没有控制台错误。 我尝试将MyMap组件移到平铺组件(L35-L45)之外,然后上述问题没有发生 我是不是用错钩子了 我的完整代码示例如下。 这是Map.tsx中的摘录: export const Tile: React.FunctionComp
我在代码中使用mapbox gl。为了初始化mapbox gl,我必须等待dom组件加载。(使用布局效果或使用效果)
初始显示没有问题,但当我按下按钮(L72)时,由mapbox gl创建的画布将卸载,没有控制台错误。
我尝试将MyMap组件移到平铺组件(L35-L45)之外,然后上述问题没有发生 我是不是用错钩子了 我的完整代码示例如下。
这是Map.tsx中的摘录:
export const Tile: React.FunctionComponent<PropsType> = ({
mapComponentLoaded,
trigger,
triggered
}) => {
const classes = useStyles({});
React.useLayoutEffect(() => { // or useEffect
// init mapbox-gl
mapComponentLoaded();
}, []); // run at once
// it doesn't works. if you clicked the button, the canvas under div#map would unmount.
const MyMap = (props: { triggered: boolean }) => (
<Paper className={classes.content}>
<div id="map" className={classes.map} />
<Typography>{props.triggered ? "fired" : "not fired"}</Typography>
</Paper>
);
return (
<div className={classes.root}>
<Grid container spacing={1} className={classes.root}>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={() => trigger()}>
Add Boundary
</Button>
</Grid>
<Grid item xs={12} className={classes.map}>
<MyMap triggered={triggered} />
</Grid>
</Grid>
</div>
);
};
export const Tile:React.FunctionComponent=({
mapComponentLoaded,
触发
触发
}) => {
const classes=useStyles({});
React.useLayoutEffect(()=>{//或useEffect
//初始化映射框gl
mapComponentLoaded();
},[]);//立即运行
//它不起作用。如果单击该按钮,div#map下的画布将卸载。
常量MyMap=(属性:{触发:布尔值})=>(
{props.triggered?“fired”:“not fired”}
);
返回(
触发器()}>
添加边界
);
};
谢谢。当您在功能组件中定义组件时,在每次渲染时都会创建一个新的组件引用,因此,在创建一个新组件时,react不会重新渲染,而是重新装载它 当您将组件从功能组件中取出时,函数的引用不会更改,因此react会正确地渲染它 现在,另一种方法是,如果不将
MyMap
作为组件呈现,而是将其作为函数调用
export const Tile: React.FunctionComponent<PropsType> = ({
mapComponentLoaded,
trigger,
triggered
}) => {
const classes = useStyles({});
React.useLayoutEffect(() => { // or useEffect
// init mapbox-gl
mapComponentLoaded();
}, []); // run at once
// it doesn't works. if you clicked the button, the canvas under div#map would unmount.
const MyMap = (props: { triggered: boolean }) => (
<Paper className={classes.content}>
<div id="map" className={classes.map} />
<Typography>{props.triggered ? "fired" : "not fired"}</Typography>
</Paper>
);
return (
<div className={classes.root}>
<Grid container spacing={1} className={classes.root}>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={() => trigger()}>
Add Boundary
</Button>
</Grid>
<Grid item xs={12} className={classes.map}>
{MyMap({triggered})}
</Grid>
</Grid>
</div>
);
};
export const Tile:React.FunctionComponent=({
mapComponentLoaded,
触发
触发
}) => {
const classes=useStyles({});
React.useLayoutEffect(()=>{//或useEffect
//初始化映射框gl
mapComponentLoaded();
},[]);//立即运行
//它不起作用。如果单击该按钮,div#map下的画布将卸载。
常量MyMap=(属性:{触发:布尔值})=>(
{props.triggered?“fired”:“not fired”}
);
返回(
触发器()}>
添加边界
{MyMap({triggered}}}
);
};
p.S.但是,将定义从函数定义中删除是一种更好的方法,因为它可以灵活地添加更多
使用React.memo
和使用挂钩进行性能优化
在这个组成部分内
不要在另一个组件内声明组件。它将重新装载每个渲染。感谢您的详细回答。我想我明白了,但我有一个问题。JSX风格和函数调用之间有什么区别?我认为两者都可能被编译为
React.createElement()
。可能当您将其作为组件呈现时,React会关心引用,当您从函数返回时,它会比较元素类型和道具以及键。虽然我还没有在React代码中检查这件事