如何避免React Native中状态变更引发react-native-map重新渲染
Hey there! Let's break down why you're seeing this behavior and how to fix it clearly.
Why React.memo wasn't working for you
Looking at your code, the core issue is that you’re defining MapViewContainer and MemorizeMap inside your parent component’s function body.
Every time your parent re-renders (like when you tap the "update" button and call setOpacity), these two components get recreated as entirely new function references. React sees this as "oh, this is a completely different component than before"—so it unmounts the old MemorizeMap and mounts a fresh one. That’s exactly why your MapView keeps reloading, even with React.memo applied.
React.memo only works when the component reference stays consistent across re-renders. If you redefine the component every time, memoization can’t do its job at all.
Why putting MapView directly in the return works
When you move <MapView> straight into your parent’s return statement, you’re no longer relying on an inner component that gets rebuilt on every render. Instead, you’re rendering the MapView element directly.
React checks if the props passed to MapView have changed (things like initialRegion, provider, style, etc.). Since none of these props update when you press the "update" button (you’re only changing opacity, which isn’t a prop for MapView), React skips re-mounting the MapView entirely and only updates other parts of the UI. That’s why the map stays loaded.
How to fix the memoization approach
To make React.memo work properly, move the definition of MapViewContainer and MemorizeMap outside your parent component. This way, their references stay consistent across parent re-renders. Here’s adjusted code to show this:
// Move these outside your parent component to preserve their reference const MapViewContainer = ({ initialRegion, mapRef, styles }) => { return ( <MapView initialRegion={initialRegion} provider="google" ref={mapRef} style={styles.map} > {/* {items.map((item, index) => { return <Marker {...{ item, index }} />; })} */} </MapView> ); }; // Custom equality check (omit the second arg if default shallow comparison works for you) const areEqual = (prevProps, nextProps) => { // Compare only the props that actually affect MapView return ( prevProps.initialRegion === nextProps.initialRegion && prevProps.styles.map === nextProps.styles.map // Add other props you need to check here ); }; const MemorizeMap = React.memo(MapViewContainer, areEqual); // Your parent component const ParentComponent = () => { const [opacity, setOpacity] = useState(1); const mapRef = useRef(); const initialRegion = { /* Your region data here */ }; const styles = StyleSheet.create({ /* Your styles here */ }); return ( <View style={styles.container}> <MemorizeMap initialRegion={initialRegion} mapRef={mapRef} styles={styles} /> <Button title="update" style={{ flex: 1 }} onPress={() => setOpacity(0)} /> </View> ); };
If you absolutely need to keep MapViewContainer inside the parent (for example, if it depends on parent state or context), you can use useMemo to preserve its reference—but moving it outside is the cleaner, more reliable approach.
Quick Recap
- Inner components defined in a parent’s function body get recreated on every re-render, breaking memoization.
- Directly rendering
MapViewavoids this because React only re-renders it if its props change. - To use
React.memoeffectively, keep memoized components outside the parent or use hooks to lock in their reference.
内容的提问来源于stack exchange,提问作者PietroPutelli

