my fork of the bluesky client

Don't render unnecessary <Portal> instances (#6217)

authored by danabra.mov and committed by GitHub 9247407c 9a10af71

Changed files
+48 -59
modules
+1 -24
modules/bottom-sheet/src/BottomSheet.tsx
··· 1 - import React from 'react' 2 - 3 - import {BottomSheetViewProps} from './BottomSheet.types' 4 - import {BottomSheetNativeComponent} from './BottomSheetNativeComponent' 5 - import {useBottomSheetPortal_INTERNAL} from './BottomSheetPortal' 6 - 7 - export const BottomSheet = React.forwardRef< 8 - BottomSheetNativeComponent, 9 - BottomSheetViewProps 10 - >(function BottomSheet(props, ref) { 11 - const Portal = useBottomSheetPortal_INTERNAL() 12 - 13 - if (__DEV__ && !Portal) { 14 - throw new Error( 15 - 'BottomSheet: You need to wrap your component tree with a <BottomSheetPortalProvider> to use the bottom sheet.', 16 - ) 17 - } 18 - 19 - return ( 20 - <Portal> 21 - <BottomSheetNativeComponent {...props} ref={ref} /> 22 - </Portal> 23 - ) 24 - }) 1 + export {BottomSheetNativeComponent as BottomSheet} from './BottomSheetNativeComponent'
+46 -34
modules/bottom-sheet/src/BottomSheetNativeComponent.tsx
··· 11 11 12 12 import {BottomSheetState, BottomSheetViewProps} from './BottomSheet.types' 13 13 import {BottomSheetPortalProvider} from './BottomSheetPortal' 14 + import {Context as PortalContext} from './BottomSheetPortal' 14 15 15 16 const screenHeight = Dimensions.get('screen').height 16 17 ··· 33 34 } 34 35 > { 35 36 ref = React.createRef<any>() 37 + 38 + static contextType = PortalContext 36 39 37 40 constructor(props: BottomSheetViewProps) { 38 41 super(props) ··· 67 70 } 68 71 69 72 render() { 73 + const Portal = this.context as React.ContextType<typeof PortalContext> 74 + if (!Portal) { 75 + throw new Error( 76 + 'BottomSheet: You need to wrap your component tree with a <BottomSheetPortalProvider> to use the bottom sheet.', 77 + ) 78 + } 79 + 80 + if (!this.state.open) { 81 + return null 82 + } 83 + 70 84 const {children, backgroundColor, ...rest} = this.props 71 85 const cornerRadius = rest.cornerRadius ?? 0 72 86 ··· 83 97 } 84 98 } 85 99 86 - if (!this.state.open) { 87 - return null 88 - } 89 - 90 100 return ( 91 - <NativeView 92 - {...rest} 93 - onStateChange={this.onStateChange} 94 - ref={this.ref} 95 - style={{ 96 - position: 'absolute', 97 - height: screenHeight, 98 - width: '100%', 99 - }} 100 - containerBackgroundColor={backgroundColor}> 101 - <View 102 - style={[ 103 - { 104 - flex: 1, 105 - backgroundColor, 106 - }, 107 - Platform.OS === 'android' && { 108 - borderTopLeftRadius: cornerRadius, 109 - borderTopRightRadius: cornerRadius, 110 - }, 111 - extraStyles, 112 - ]}> 101 + <Portal> 102 + <NativeView 103 + {...rest} 104 + onStateChange={this.onStateChange} 105 + ref={this.ref} 106 + style={{ 107 + position: 'absolute', 108 + height: screenHeight, 109 + width: '100%', 110 + }} 111 + containerBackgroundColor={backgroundColor}> 113 112 <View 114 - onLayout={e => { 115 - const {height} = e.nativeEvent.layout 116 - this.setState({viewHeight: height}) 117 - this.updateLayout() 118 - }}> 119 - <BottomSheetPortalProvider>{children}</BottomSheetPortalProvider> 113 + style={[ 114 + { 115 + flex: 1, 116 + backgroundColor, 117 + }, 118 + Platform.OS === 'android' && { 119 + borderTopLeftRadius: cornerRadius, 120 + borderTopRightRadius: cornerRadius, 121 + }, 122 + extraStyles, 123 + ]}> 124 + <View 125 + onLayout={e => { 126 + const {height} = e.nativeEvent.layout 127 + this.setState({viewHeight: height}) 128 + this.updateLayout() 129 + }}> 130 + <BottomSheetPortalProvider>{children}</BottomSheetPortalProvider> 131 + </View> 120 132 </View> 121 - </View> 122 - </NativeView> 133 + </NativeView> 134 + </Portal> 123 135 ) 124 136 } 125 137 }
+1 -1
modules/bottom-sheet/src/BottomSheetPortal.tsx
··· 4 4 5 5 type PortalContext = React.ElementType<{children: React.ReactNode}> 6 6 7 - const Context = React.createContext({} as PortalContext) 7 + export const Context = React.createContext({} as PortalContext) 8 8 9 9 export const useBottomSheetPortal_INTERNAL = () => React.useContext(Context) 10 10