How to Structure Your React Native Application

Photo by Jacob Morch on Unsplash

Never ever mix any of the aforementioned kinds into a single file, but instead use one file per kind and custom hooks for handling your domain and UI logic.

// ./src/components/MyComponent.jsconst MyComponent = () => {  
const scrollY = new Animated.Value(0)
const height = new Animated.Value(0)
const opacity = scrollY.interpolate({
inputRange: [0, 45],
outputRange: [0, 1]
})
const {dark} = useTheme() const [info, setInfo] = useState({loading: true, info: undefined})

useEffect(() => {
(async () => {
// Fetch information on mount
const result = await fetchSomeData()
setInfo({loading: false, info: result})
})()
}, [])
return info.loading ? <Loading /> : (
<>
<Animated.View
style={[styles.header, {opacity, height}]}>
<BlurView
blurType={dark ? 'dark' : 'light'}
blurRadius={100}
style={styles.blur} />

<View
onLayout={Animated.event(
[
{
nativeEvent: {layout: {height}}
}
],
{ useNativeDriver: false },
)}
style={[
styles.headline,
{paddingTop: useSafeAreaInsets().top},
]}>

<Header>
My Header above blurred background
</Header>
</View>
</Animated.View>
<Animated.ScrollView
style={[
styles.container,
{paddingTop: useSafeAreaInsets().top}
]}
showsVerticalScrollIndicator={false}
contentInsetAdjustmentBehavior='automatic'
scrollEventThrottle={1}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: scrollY
}
}
}
],
{ useNativeDriver: false }
)}>
<Some Content info={info.result} />
</Animated.ScrollView>
</>
)
}
const styles = StyleSheet.create({
header: {
...StyleSheet.absoluteFillObject,
bottom: undefined,
elevation: 1,
zIndex: 1
},
blur: {
flex: 1
}
})
src
|-- components
|-- MyComponent.js
src
|-- components
|-- MyComponent
|-- hooks
| -- index.js
| -- useData.js
| -- useLayout.js
|-- index.js
// ./src/components/MyComponent/hooks/index.jsexport {default as useData} from './useData'
export {default as useLayout} from './useLayout'
// ./src/components/MyComponent/hooks/useData.jsconst useData = () => {  
const [info, setInfo] = useState({loading: true, info: undefined})

useEffect(() => {
(async () => {
// Fetch information on mount
const result = await fetchSomeData()
setInfo({loading: false, info: result})
})()
}, [])

return info
}
// Split default exporting and hook declaration to avoid anonymous // symbols in logs and dumps
export default useData
// ./src/components/MyComponent/hooks/useLayout.jsconst useLayout = () => {  
const scrollY = new Animated.Value(0)
const height = new Animated.Value(0)
const opacity = scrollY.interpolate({
inputRange: [0, 45],
outputRange: [0, 1]
})
const {dark} = useTheme() const onLayout = Animated.event(
[
{
nativeEvent: {layout: {height}}
}
],
{useNativeDriver: false}
)
const onScroll = Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: scrollY
}
}
}
],
{useNativeDriver: false}
)

return {
blurType: dark ? 'dark' : 'light',
opacity,
height,
onLayout,
paddingTop: useSafeAreaInsets().top,
onScroll
}
}
export default useLayout
// ./src/components/MyComponent/index.jsimport {useData, useLayout} from './hooks'const MyComponent = () => {  
const {
blurType,
opacity,
height,
onLayout,
paddingTop
} = useLayout()
const {loading, result} = useData() return loading ? <Loading /> : (
<>
<Animated.View style={[styles.header, {opacity, height}]}>
<BlurView
blurType={blurType}
blurRadius={100}
style={styles.blur} />
<View
onLayout={onLayout}
style={[styles.headline, {paddingTop}]}>
<Header>
My Header above blurred background
</Header>
</View>
</Animated.View>
<Animated.ScrollView
style={[styles.container, {paddingTop}]}
showsVerticalScrollIndicator={false}
contentInsetAdjustmentBehavior='automatic'
scrollEventThrottle={1}
onScroll={onScroll}>
<Some Content info={result} />
</Animated.ScrollView>
</>
)
}
const styles = StyleSheet.create({
header: {
...StyleSheet.absoluteFillObject,
bottom: undefined,
elevation: 1,
zIndex: 1
},
blur: {
flex: 1
}
})

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store