Skip to content

Commit 3e9e5c8

Browse files
committed
RFC: Memoize style objects to prevent re-renders of memoized components
1 parent bfb6b30 commit 3e9e5c8

File tree

4 files changed

+62
-13
lines changed

4 files changed

+62
-13
lines changed

example/src/examples/Memoization.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react'
2+
import { Text, View, type StyleProp, type TextStyle, Button } from 'react-native'
3+
import { createStyleSheet, useStyles } from '../styles'
4+
5+
export const Memoization: React.FunctionComponent = () => {
6+
const { styles } = useStyles(stylesheet)
7+
const [ count, setCount ] = React.useState(0)
8+
9+
return (
10+
<View style={styles.container}>
11+
<Memoized text="With breakpoints" style={styles.withBreakpoints} />
12+
<Memoized text="No breakpoints" style={styles.noBreakpoints} />
13+
<Memoized text="Static" style={staticStyles.static} />
14+
<Button title={`Re-render (${count})`} onPress={() => setCount(count => count + 1)} />
15+
</View>
16+
)
17+
}
18+
19+
const Memoized = React.memo<{text: string; style: StyleProp<TextStyle>}>(({ text, style }) =>
20+
<Text style={style}>{text} ({useRenderCount()})</Text>
21+
)
22+
23+
const useRenderCount = () => {
24+
const count = React.useRef(0)
25+
count.current++
26+
27+
return count.current
28+
}
29+
30+
const stylesheet = createStyleSheet({
31+
container: {
32+
flex: 1,
33+
justifyContent: 'center',
34+
alignItems: 'center',
35+
alignContent: 'space-between',
36+
resizeMode: 'contain'
37+
},
38+
withBreakpoints: {
39+
fontSize: 18,
40+
color: {
41+
xs: 'red',
42+
md: 'blue'
43+
}
44+
},
45+
noBreakpoints: {
46+
fontSize: 18
47+
}
48+
})
49+
50+
const staticStyles = createStyleSheet({
51+
static: {
52+
fontSize: 18
53+
}
54+
})

example/src/examples/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export { Theme } from './Theme'
44
export { Breakpoints } from './Breakpoints'
55
export { MediaQueries } from './MediaQueries'
66
export { Extreme } from './Extreme'
7+
export { Memoization } from './Memoization'

src/createUnistyles.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useContext } from 'react'
1+
import { useContext, useMemo, useEffect, useRef } from 'react'
22
import { StyleSheet } from 'react-native'
33
import type {
44
Breakpoints,
@@ -36,12 +36,13 @@ export const createUnistyles = <B extends Breakpoints, T = {}>(breakpoints: B) =
3636
}
3737
}
3838

39-
const parsedStyles = typeof stylesheet === 'function'
39+
const parsedStyles = useMemo(() => typeof stylesheet === 'function'
4040
? stylesheet(theme)
41-
: stylesheet
41+
: stylesheet, [theme, stylesheet])
42+
4243
const breakpoint = getBreakpointFromScreenWidth<B>(screenSize.width, sortedBreakpointEntries)
4344

44-
const dynamicStyleSheet = Object
45+
const dynamicStyleSheet = useMemo(() => Object
4546
.entries(parsedStyles)
4647
.reduce((acc, [key, value]) => {
4748
const style = value as CustomNamedStyles<ST, B>
@@ -57,7 +58,7 @@ export const createUnistyles = <B extends Breakpoints, T = {}>(breakpoints: B) =
5758
...acc,
5859
[key]: parseStyle<ST, B>(style, breakpoint, screenSize, sortedBreakpointEntries)
5960
})
60-
}, {} as ST)
61+
}, {} as ST), [breakpoint, screenSize, sortedBreakpointEntries])
6162

6263
return {
6364
theme,

src/hooks/useDimensions.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
import { useWindowDimensions } from 'react-native'
22
import type { ScreenSize } from '../types'
33

4-
export const useDimensions = (): ScreenSize => {
5-
const { width, height } = useWindowDimensions()
6-
7-
return {
8-
width,
9-
height
10-
}
11-
}
4+
export const useDimensions = (): ScreenSize => useWindowDimensions()

0 commit comments

Comments
 (0)