gpt4 book ai didi

reactjs - react useCallback : useCallback is still re-rendering function each time

转载 作者:行者123 更新时间:2023-12-04 12:28:53 25 4
gpt4 key购买 nike

我对 useMemo 还很陌生和 useCallback react 中的钩子(Hook),我有点不明白为什么即使我检查的变量保持不变,我的函数仍然继续重新渲染。目前我正在尝试构建一个谷歌地图,允许用户打开和关闭 map 上显示的某些标记。我的功能组件应该只需要在加载时呈现这些标记一次,然后在此之后记住它们,因为它们之后才被打开/关闭。现在我明白了这样的钩子(Hook)只能进行浅层比较的概念,但我正在比较 bool 值,我认为这些钩子(Hook)能够理解。
这是我当前的 map 文件:

// constants are above

function Map() {

const {isLoaded} = useJsApiLoader({
googleMapsApiKey: env.GOOGLE_MAPS_API.API_KEY,
libraries: libs
})

const [map, setMap] = useState(null);
const [places,setPlaces] = useState([]);
const [places2,setPlaces2] = useState([]);
const [heatMap,setHeatMap] = useState([]);
const [fetchingData, setFetchingData] = useState(true);
const [showPlaces,setShowPlaces] = useState(true);
const [showPlaces2,setShowPlaces2] = useState(false);
const [showHeatMap,setShowHeatMap] = useState(false);

useEffect(() => {
let mounted = true;

if(mounted){
socket.emit('getMapAnalytics', ([heatmap,places,places2]) => {
console.log({heatmap})
setPlaces(places);
setPlaces2(places2);
setHeatMap(heatmap);
setFetchingData(false);
});
}

return () => {
mounted = false;
}
},[])

const onLoad = useCallback((map) => {
setMap(map);
},[])

const onUnmount = useCallback((map) => {
setMap(null);
},[]);

const renderPlacesMarkers = useCallback(() => {
console.log('rendering places')
if(showPlaces){
return places.map(place => (
<Marker icon={icon} key={place.ID} title={place.Name} position={{lat:place.Latitude,lng:place.Longitude}}/>
))
}
return null;
},[showPlaces]);

const renderPlaces2Markers = useCallback(() => {
console.log('rendering places2')
if(showPlaces2){
return places2.map(place => (
<Marker key={place.ID} title={place.ID} position={{lat:place.Latitude,lng:place.Longitude}}/>
))
}
return null;
},[showPlaces2]);

const renderHeatMap = useCallback(() => {
console.log('rendering heat map')
if(showHeatMap){
const mapData = heatMap.map(location => ({
location: new google.maps.LatLng(location.Latitude,location.Longitude), weight: location.population_density
}))

return (<HeatmapLayer data={mapData} options={{gradient: gradient}} />)
}
return null;
},[showHeatMap]);

const onChecked = (e) => {
switch(e.target.id){
case 'places': setShowPlaces(e.target.checked);
break;
case 'places2': setShowPlaces2(e.target.checked);
break;
case 'heat-map': setShowHeatMap(e.target.checked);
break;
}
}

return isLoaded && !fetchingData ? (
<div id="map-container">
<div id="top-bar" style={{display: 'flex', justifyContent:'space-evenly'}}>
<div style={{display: 'flex'}}>
<input type="checkbox" id="places" checked={showPlaces} onChange={onChecked}></input><label>techs</label>
</div>
<div style={{display: 'flex'}}>
<input type="checkbox" id="places2" checked={showPlaces2} onChange={onChecked}></input><label>kiosks</label>
</div>
<div style={{display: 'flex'}}>
<input type="checkbox" id="heat-map" checked={showHeatMap} onChange={onChecked}></input><label>heatmap</label>
</div>
</div>
<GoogleMap mapContainerStyle={containerStyle} center={center} zoom={10} onLoad={onLoad} onUnmount={onUnmount}>
{renderPlacesMarkers()}
{renderPlaces2Markers()}
{renderHeatMap()}
</GoogleMap>
</div>
) : <Spinner margin="margin-25"></Spinner>
}

export default memo(Map);

我试过设置 useCallback参数到其他东西,例如places和places2的数组长度,但最终仍然重新渲染每个函数。
我唯一能想到的就是每次都重新渲染这些方法是因为我要返回一组 JSX 元素,但是我在网上找不到很好的例子。如果有人能指出我正确的方向以正确理解为什么会发生这种情况,那就太好了。蒂亚!

最佳答案

看来你是误会了useCallback .
如果您 useCallback一些功能,它不会是重新创建 如果依赖项没有改变。但是如果你手动调用它,它将始终运行 .
当您单击任何复选框时, map 会重新呈现。如果说 renderPlaces 的依赖项, 没有改变,函数将保持不变,但之后你还是在渲染中手动调用它:renderPlaces() .
根据您的设置,我的建议是改为制作 renderPlaces和其他两个正常的功能 组件 (并在 Map 组件之外定义它们)并应用 React.memo在他们。
一般来说,我建议渲染组件而不是调用它们,例如更好用<Component/>而不是 Component() .在功能组件中定义功能组件是一个坏主意,因为 react 协调算法会认为它们在每次渲染时都是不同的类型(因为如果你在函数内部定义函数,它每次都会重新创建)。

关于reactjs - react useCallback : useCallback is still re-rendering function each time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68318140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com