Don't render unnecessary <Portal> instances (#6217)
This commit is contained in:
@@ -1,24 +1 @@
|
|||||||
import React from 'react'
|
export {BottomSheetNativeComponent as BottomSheet} from './BottomSheetNativeComponent'
|
||||||
|
|
||||||
import {BottomSheetViewProps} from './BottomSheet.types'
|
|
||||||
import {BottomSheetNativeComponent} from './BottomSheetNativeComponent'
|
|
||||||
import {useBottomSheetPortal_INTERNAL} from './BottomSheetPortal'
|
|
||||||
|
|
||||||
export const BottomSheet = React.forwardRef<
|
|
||||||
BottomSheetNativeComponent,
|
|
||||||
BottomSheetViewProps
|
|
||||||
>(function BottomSheet(props, ref) {
|
|
||||||
const Portal = useBottomSheetPortal_INTERNAL()
|
|
||||||
|
|
||||||
if (__DEV__ && !Portal) {
|
|
||||||
throw new Error(
|
|
||||||
'BottomSheet: You need to wrap your component tree with a <BottomSheetPortalProvider> to use the bottom sheet.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Portal>
|
|
||||||
<BottomSheetNativeComponent {...props} ref={ref} />
|
|
||||||
</Portal>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {requireNativeModule, requireNativeViewManager} from 'expo-modules-core'
|
|||||||
|
|
||||||
import {BottomSheetState, BottomSheetViewProps} from './BottomSheet.types'
|
import {BottomSheetState, BottomSheetViewProps} from './BottomSheet.types'
|
||||||
import {BottomSheetPortalProvider} from './BottomSheetPortal'
|
import {BottomSheetPortalProvider} from './BottomSheetPortal'
|
||||||
|
import {Context as PortalContext} from './BottomSheetPortal'
|
||||||
|
|
||||||
const screenHeight = Dimensions.get('screen').height
|
const screenHeight = Dimensions.get('screen').height
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
> {
|
> {
|
||||||
ref = React.createRef<any>()
|
ref = React.createRef<any>()
|
||||||
|
|
||||||
|
static contextType = PortalContext
|
||||||
|
|
||||||
constructor(props: BottomSheetViewProps) {
|
constructor(props: BottomSheetViewProps) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -67,6 +70,17 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const Portal = this.context as React.ContextType<typeof PortalContext>
|
||||||
|
if (!Portal) {
|
||||||
|
throw new Error(
|
||||||
|
'BottomSheet: You need to wrap your component tree with a <BottomSheetPortalProvider> to use the bottom sheet.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.state.open) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const {children, backgroundColor, ...rest} = this.props
|
const {children, backgroundColor, ...rest} = this.props
|
||||||
const cornerRadius = rest.cornerRadius ?? 0
|
const cornerRadius = rest.cornerRadius ?? 0
|
||||||
|
|
||||||
@@ -83,43 +97,41 @@ export class BottomSheetNativeComponent extends React.Component<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.open) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NativeView
|
<Portal>
|
||||||
{...rest}
|
<NativeView
|
||||||
onStateChange={this.onStateChange}
|
{...rest}
|
||||||
ref={this.ref}
|
onStateChange={this.onStateChange}
|
||||||
style={{
|
ref={this.ref}
|
||||||
position: 'absolute',
|
style={{
|
||||||
height: screenHeight,
|
position: 'absolute',
|
||||||
width: '100%',
|
height: screenHeight,
|
||||||
}}
|
width: '100%',
|
||||||
containerBackgroundColor={backgroundColor}>
|
}}
|
||||||
<View
|
containerBackgroundColor={backgroundColor}>
|
||||||
style={[
|
|
||||||
{
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor,
|
|
||||||
},
|
|
||||||
Platform.OS === 'android' && {
|
|
||||||
borderTopLeftRadius: cornerRadius,
|
|
||||||
borderTopRightRadius: cornerRadius,
|
|
||||||
},
|
|
||||||
extraStyles,
|
|
||||||
]}>
|
|
||||||
<View
|
<View
|
||||||
onLayout={e => {
|
style={[
|
||||||
const {height} = e.nativeEvent.layout
|
{
|
||||||
this.setState({viewHeight: height})
|
flex: 1,
|
||||||
this.updateLayout()
|
backgroundColor,
|
||||||
}}>
|
},
|
||||||
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
|
Platform.OS === 'android' && {
|
||||||
|
borderTopLeftRadius: cornerRadius,
|
||||||
|
borderTopRightRadius: cornerRadius,
|
||||||
|
},
|
||||||
|
extraStyles,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
onLayout={e => {
|
||||||
|
const {height} = e.nativeEvent.layout
|
||||||
|
this.setState({viewHeight: height})
|
||||||
|
this.updateLayout()
|
||||||
|
}}>
|
||||||
|
<BottomSheetPortalProvider>{children}</BottomSheetPortalProvider>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</NativeView>
|
||||||
</NativeView>
|
</Portal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {createPortalGroup_INTERNAL} from './lib/Portal'
|
|||||||
|
|
||||||
type PortalContext = React.ElementType<{children: React.ReactNode}>
|
type PortalContext = React.ElementType<{children: React.ReactNode}>
|
||||||
|
|
||||||
const Context = React.createContext({} as PortalContext)
|
export const Context = React.createContext({} as PortalContext)
|
||||||
|
|
||||||
export const useBottomSheetPortal_INTERNAL = () => React.useContext(Context)
|
export const useBottomSheetPortal_INTERNAL = () => React.useContext(Context)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user