Skip to content

Commit 139ea33

Browse files
efokenAndarist
andauthored
Use StyleSheet.create in React Native (#2060)
* Use `StyleSheet.create` in React Native * Flatten the styles before passing them to `StyleSheet.create` * Fix primitives tests * Update snapshots * Fix flow errors * Add changeset Co-authored-by: Mateusz Burzyński <[email protected]>
1 parent 20d2249 commit 139ea33

File tree

8 files changed

+210
-209
lines changed

8 files changed

+210
-209
lines changed

.changeset/strong-cooks-drum.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@emotion/native': major
3+
'@emotion/primitives': major
4+
'@emotion/primitives-core': major
5+
---
6+
7+
`StyleSheet.create` is used now under the hood. This means that when used in combination with React Native Web atomic class names are applied on components instead of inline styles.

packages/native/test/__snapshots__/native-styled.test.js.snap

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ exports[`Emotion native styled primitive should work with \`withComponent\` 1`]
55
decor="hotpink"
66
style={
77
Array [
8-
Object {
9-
"color": "hotpink",
10-
},
8+
77,
119
undefined,
1210
]
1311
}
@@ -21,9 +19,7 @@ exports[`Emotion native styled should pass props in withComponent 1`] = `
2119
color="green"
2220
style={
2321
Array [
24-
Object {
25-
"backgroundColor": "green",
26-
},
22+
81,
2723
undefined,
2824
]
2925
}
@@ -35,9 +31,7 @@ exports[`Emotion native styled should pass props in withComponent 2`] = `
3531
color="hotpink"
3632
style={
3733
Array [
38-
Object {
39-
"backgroundColor": "hotpink",
40-
},
34+
82,
4135
undefined,
4236
]
4337
}
@@ -55,12 +49,7 @@ exports[`Emotion native styled should render <Image /> 1`] = `
5549
}
5650
style={
5751
Array [
58-
Object {
59-
"borderBottomLeftRadius": 2,
60-
"borderBottomRightRadius": 2,
61-
"borderTopLeftRadius": 2,
62-
"borderTopRightRadius": 2,
63-
},
52+
83,
6453
undefined,
6554
]
6655
}
@@ -71,9 +60,7 @@ exports[`Emotion native styled should render primitive with style prop 1`] = `
7160
<Text
7261
style={
7362
Array [
74-
Object {
75-
"color": "hotpink",
76-
},
63+
77,
7764
Object {
7865
"padding": 10,
7966
},
@@ -89,10 +76,7 @@ exports[`Emotion native styled should render styles correctly from all nested st
8976
backgroundColor="blue"
9077
style={
9178
Array [
92-
Object {
93-
"backgroundColor": "blue",
94-
"color": "hotpink",
95-
},
79+
86,
9680
undefined,
9781
]
9882
}
@@ -106,13 +90,7 @@ exports[`Emotion native styled should render the primitive on changing the props
10690
decor="hotpink"
10791
style={
10892
Array [
109-
Object {
110-
"color": "hotpink",
111-
"paddingBottom": 20,
112-
"paddingLeft": 20,
113-
"paddingRight": 20,
114-
"paddingTop": 20,
115-
},
93+
76,
11694
undefined,
11795
]
11896
}
@@ -126,11 +104,7 @@ exports[`Emotion native styled should render the primitive when styles applied u
126104
back="red"
127105
style={
128106
Array [
129-
Object {
130-
"backgroundColor": "red",
131-
"color": "red",
132-
"fontSize": 20,
133-
},
107+
74,
134108
Object {
135109
"fontSize": 40,
136110
},
@@ -145,9 +119,7 @@ exports[`Emotion native styled should style any other component 1`] = `
145119
<Text
146120
style={
147121
Array [
148-
Object {
149-
"color": "hotpink",
150-
},
122+
77,
151123
undefined,
152124
]
153125
}
@@ -160,10 +132,8 @@ exports[`Emotion native styled should work with StyleSheet.create API 1`] = `
160132
<Text
161133
style={
162134
Array [
163-
Object {
164-
"fontSize": 10,
165-
},
166-
74,
135+
79,
136+
78,
167137
]
168138
}
169139
>
@@ -175,9 +145,7 @@ exports[`Emotion native styled should work with theming from @emotion/react 1`]
175145
<Text
176146
style={
177147
Array [
178-
Object {
179-
"color": "magenta",
180-
},
148+
75,
181149
undefined,
182150
]
183151
}
Lines changed: 76 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,134 @@
11
import { css } from '@emotion/native'
2+
import { StyleSheet } from 'react-native'
23

34
jest.mock('react-native')
45

56
let returnArguments = (...args) => args
67

78
describe('Emotion native css', () => {
89
test('basic', () => {
9-
expect(css`
10-
color: hotpink;
11-
${{ backgroundColor: 'green' }};
12-
`).toEqual({ color: 'hotpink', backgroundColor: 'green' })
13-
expect(css({ color: 'green' })).toEqual({ color: 'green' })
14-
expect(css([{ color: 'green' }, `background-color:yellow;`])).toEqual({
10+
expect(
11+
StyleSheet.flatten(css`
12+
color: hotpink;
13+
${{ backgroundColor: 'green' }};
14+
`)
15+
).toEqual({ color: 'hotpink', backgroundColor: 'green' })
16+
expect(StyleSheet.flatten(css({ color: 'green' }))).toEqual({
17+
color: 'green'
18+
})
19+
expect(
20+
StyleSheet.flatten(css([{ color: 'green' }, `background-color:yellow;`]))
21+
).toEqual({
1522
color: 'green',
1623
backgroundColor: 'yellow'
1724
})
18-
expect(css([{ color: 'green' }])).toEqual({ color: 'green' })
25+
expect(StyleSheet.flatten(css([{ color: 'green' }]))).toEqual({
26+
color: 'green'
27+
})
1928
})
2029

2130
test('order with string and object', () => {
2231
// this test checks the keys instead of the objects
2332
// because we care about the order of the keys
2433
expect(
34+
// $FlowFixMe
2535
Object.keys(
26-
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
36+
StyleSheet.flatten(
37+
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
38+
)
2739
)
2840
).toEqual(['color', 'backgroundColor', 'flex'])
2941
expect(
42+
// $FlowFixMe
3043
Object.keys(
31-
css([
32-
[{ color: 'green' }, `background-color:yellow;`],
33-
{
34-
flex: 2
35-
}
36-
])
44+
StyleSheet.flatten(
45+
css([
46+
[{ color: 'green' }, `background-color:yellow;`],
47+
{
48+
flex: 2
49+
}
50+
])
51+
)
3752
)
3853
).toEqual(['color', 'backgroundColor', 'flex'])
3954
expect(
55+
// $FlowFixMe
4056
Object.keys(
41-
css([
42-
{ color: 'green' },
43-
[
44-
`background-color:yellow;`,
45-
{
46-
flex: 2
47-
}
48-
]
49-
])
57+
StyleSheet.flatten(
58+
css([
59+
{ color: 'green' },
60+
[
61+
`background-color:yellow;`,
62+
{
63+
flex: 2
64+
}
65+
]
66+
])
67+
)
5068
)
5169
).toEqual(['color', 'backgroundColor', 'flex'])
5270
expect(
71+
// $FlowFixMe
5372
Object.keys(
54-
css([
55-
{ color: 'green' },
56-
[
57-
{ flex: 8 },
58-
`background-color:yellow;`,
59-
[`flex-grow: 1;`, { flexDirection: 'row' }]
60-
]
61-
])
73+
StyleSheet.flatten(
74+
css([
75+
{ color: 'green' },
76+
[
77+
{ flex: 8 },
78+
`background-color:yellow;`,
79+
[`flex-grow: 1;`, { flexDirection: 'row' }]
80+
]
81+
])
82+
)
6283
)
6384
).toEqual(['color', 'flex', 'backgroundColor', 'flexGrow', 'flexDirection'])
6485
})
6586

6687
it('allows function interpolations when this.mergedProps is defined', () => {
6788
expect(
68-
css.call({ thing: true }, props => ({
69-
color: props.thing && 'hotpink'
70-
}))
89+
StyleSheet.flatten(
90+
css.call({ thing: true }, props => ({
91+
color: props.thing && 'hotpink'
92+
}))
93+
)
7194
).toEqual({ color: 'hotpink' })
7295
})
7396

7497
it('works with nested functions', () => {
7598
expect(
76-
css.call({ thing: true }, props => () => ({
77-
color: props.thing && 'hotpink'
78-
}))
99+
StyleSheet.flatten(
100+
css.call({ thing: true }, props => () => ({
101+
color: props.thing && 'hotpink'
102+
}))
103+
)
79104
).toEqual({ color: 'hotpink' })
80105
})
81106

82107
it('works with functions in tagged template literals', () => {
83108
expect(
84-
css.call(
85-
{},
86-
...returnArguments`
109+
StyleSheet.flatten(
110+
css.call(
111+
{},
112+
...returnArguments`
87113
color: ${() => 'hotpink'};
88114
`
115+
)
89116
)
90117
).toEqual({ color: 'hotpink' })
91118
})
92119

93120
test('last arg falsy and string before that', () => {
94-
expect(css('color:hotpink;', false)).toEqual({ color: 'hotpink' })
121+
expect(StyleSheet.flatten(css('color:hotpink;', false))).toEqual({
122+
color: 'hotpink'
123+
})
95124
})
96125

97126
test('falsy value in the middle', () => {
98127
expect(
99-
css`
128+
StyleSheet.flatten(css`
100129
color: ${false};
101130
background-color: hotpink;
102-
`
131+
`)
103132
).toEqual({ backgroundColor: 'hotpink' })
104133
})
105134

@@ -108,10 +137,10 @@ describe('Emotion native css', () => {
108137
color: hotpink;
109138
`
110139
expect(
111-
css`
140+
StyleSheet.flatten(css`
112141
background-color: green;
113142
${firstStyle};
114-
`
143+
`)
115144
).toEqual({ backgroundColor: 'green', color: 'hotpink' })
116145
})
117146

@@ -128,7 +157,7 @@ describe('Emotion native css', () => {
128157
// color: red;
129158
`
130159

131-
expect(styles).toEqual({ color: 'hotpink' })
132-
expect(anotherStyles).toEqual({ fontSize: 10 })
160+
expect(StyleSheet.flatten(styles)).toEqual({ color: 'hotpink' })
161+
expect(StyleSheet.flatten(anotherStyles)).toEqual({ fontSize: 10 })
133162
})
134163
})

packages/primitives-core/src/css.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { interleave } from './utils'
77
// this is done so we don't create a new
88
// handleInterpolation function on every css call
99
let styles
10+
let generated = {}
1011
let buffer = ''
1112
let lastType
1213

@@ -102,7 +103,14 @@ export function createCss(StyleSheet: Object) {
102103
buffer = prevBuffer
103104
}
104105

105-
return StyleSheet.flatten(styles)
106+
const hash = JSON.stringify(styles)
107+
if (!generated[hash]) {
108+
const styleSheet = StyleSheet.create({
109+
generated: StyleSheet.flatten(styles)
110+
})
111+
generated[hash] = styleSheet.generated
112+
}
113+
return generated[hash]
106114
}
107115
}
108116

0 commit comments

Comments
 (0)