I'm using the BottomSheetModal to display a list of all countries in a bottom sheet. But I get the error message 'BottomSheetModalInternalContext' cannot be null!
when navigating to the screen that includes the bottom modal.
I assume that the error occurs because I initialize the ref (bottomSheetModalRef
) with null, but I don't know how else I can create the ref without passing in null.
Excerpt of the full error message
'BottomSheetModalInternalContext' cannot be null!
This error is located at:
in ForwardRef(BottomSheetModal)
in ForwardRef(BottomSheetModal) (at CountryPicker.tsx:89)
in RCTView (at View.js:34)
in View (created by ForwardRef)
in ForwardRef (at CountryPicker.tsx:74)
...
//CountryPicker.tsx
import React, { useRef, useState, useEffect, useMemo } from 'react'
import {
ActivityIndicator,
TextInput,
TouchableOpacity,
StyleSheet,
} from 'react-native'
import axios from 'axios'
import { BottomSheetFlatList, BottomSheetModal } from '@gorhom/bottom-sheet'
import { Box, Text } from '../../theme/theme'
interface Props {
onCountrySelected: (country: string) => void
value: string
}
interface CountryProps {
flag: string
name: string
alpha3Code: string
}
const Country = (country: CountryProps) => (
<Box>
<Text>{country.name}</Text>
</Box>
)
const CountryPicker: React.FC<Props> = ({ onCountrySelected, value }) => {
const [countries, setCountries] = useState<CountryProps[]>([])
const [isLoading, setIsLoading] = useState(false)
const bottomSheetModalRef = useRef<BottomSheetModal>(null)
const handlePresentPress = () => {
if (bottomSheetModalRef.current) bottomSheetModalRef.current.present()
}
const snapPoints = useMemo(() => ['20%', '40%'], [])
const getAllCountries = async () => {
setIsLoading(true)
const res = await axios.get(
'https://restcountries.eu/rest/v2/all?fields=name;flag;alpha3Code',
)
const data = await res.data
setCountries(data)
setIsLoading(false)
}
const getCountryByCode = async (code: string) => {
setIsLoading(true)
const res = await axios.get(
`https://restcountries.eu/rest/v2/alpha/${code}?fields=name;flag;alpha3Code`,
)
const data = await res.data
setCountries(data)
setIsLoading(false)
}
const renderCountry = (country: CountryProps) => {
return (
<Country
flag={country.flag}
name={country.name}
alpha3Code={country.alpha3Code}
/>
)
}
useEffect(() => {
getAllCountries()
}, [])
return (
<Box>
<TouchableOpacity onPress={handlePresentPress}>
<Box marginVertical="xs">
<Box
paddingVertical="inputS"
paddingHorizontal="inputM"
borderRadius="s"
backgroundColor="inputBG"
borderColor="inputBG"
borderWidth={2}
>
<TextInput placeholder="Country" value={value} editable={false} />
</Box>
</Box>
</TouchableOpacity>
<BottomSheetModal ref={bottomSheetModalRef} snapPoints={snapPoints}>
{isLoading ? (
<ActivityIndicator />
) : (
<BottomSheetFlatList
data={countries}
keyExtractor={(item: CountryProps) => item.alpha3Code}
renderItem={(countries) => renderCountry(countries.item)}
contentContainerStyle={styles.contentContainer}
onRefresh={getAllCountries}
bounces={false}
/>
)}
</BottomSheetModal>
</Box>
)
}
const styles = StyleSheet.create({
contentContainer: {
flex: 1,
},
})
export default CountryPicker
confirm you surround your App.tsx
file with BottomSheetModalProvider
return (
<BottomSheetModalProvider>
....
</BottomSheetModalProvider>
);