Skip to content

Commit

Permalink
Use StyleSheet.create in React Native (#2060)
Browse files Browse the repository at this point in the history
* 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 <mateuszburzynski@gmail.com>
  • Loading branch information
efoken and Andarist committed Nov 11, 2020
1 parent 20d2249 commit 139ea33
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 209 deletions.
7 changes: 7 additions & 0 deletions .changeset/strong-cooks-drum.md
@@ -0,0 +1,7 @@
---
'@emotion/native': major
'@emotion/primitives': major
'@emotion/primitives-core': major
---

`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.
56 changes: 12 additions & 44 deletions packages/native/test/__snapshots__/native-styled.test.js.snap
Expand Up @@ -5,9 +5,7 @@ exports[`Emotion native styled primitive should work with \`withComponent\` 1`]
decor="hotpink"
style={
Array [
Object {
"color": "hotpink",
},
77,
undefined,
]
}
Expand All @@ -21,9 +19,7 @@ exports[`Emotion native styled should pass props in withComponent 1`] = `
color="green"
style={
Array [
Object {
"backgroundColor": "green",
},
81,
undefined,
]
}
Expand All @@ -35,9 +31,7 @@ exports[`Emotion native styled should pass props in withComponent 2`] = `
color="hotpink"
style={
Array [
Object {
"backgroundColor": "hotpink",
},
82,
undefined,
]
}
Expand All @@ -55,12 +49,7 @@ exports[`Emotion native styled should render <Image /> 1`] = `
}
style={
Array [
Object {
"borderBottomLeftRadius": 2,
"borderBottomRightRadius": 2,
"borderTopLeftRadius": 2,
"borderTopRightRadius": 2,
},
83,
undefined,
]
}
Expand All @@ -71,9 +60,7 @@ exports[`Emotion native styled should render primitive with style prop 1`] = `
<Text
style={
Array [
Object {
"color": "hotpink",
},
77,
Object {
"padding": 10,
},
Expand All @@ -89,10 +76,7 @@ exports[`Emotion native styled should render styles correctly from all nested st
backgroundColor="blue"
style={
Array [
Object {
"backgroundColor": "blue",
"color": "hotpink",
},
86,
undefined,
]
}
Expand All @@ -106,13 +90,7 @@ exports[`Emotion native styled should render the primitive on changing the props
decor="hotpink"
style={
Array [
Object {
"color": "hotpink",
"paddingBottom": 20,
"paddingLeft": 20,
"paddingRight": 20,
"paddingTop": 20,
},
76,
undefined,
]
}
Expand All @@ -126,11 +104,7 @@ exports[`Emotion native styled should render the primitive when styles applied u
back="red"
style={
Array [
Object {
"backgroundColor": "red",
"color": "red",
"fontSize": 20,
},
74,
Object {
"fontSize": 40,
},
Expand All @@ -145,9 +119,7 @@ exports[`Emotion native styled should style any other component 1`] = `
<Text
style={
Array [
Object {
"color": "hotpink",
},
77,
undefined,
]
}
Expand All @@ -160,10 +132,8 @@ exports[`Emotion native styled should work with StyleSheet.create API 1`] = `
<Text
style={
Array [
Object {
"fontSize": 10,
},
74,
79,
78,
]
}
>
Expand All @@ -175,9 +145,7 @@ exports[`Emotion native styled should work with theming from @emotion/react 1`]
<Text
style={
Array [
Object {
"color": "magenta",
},
75,
undefined,
]
}
Expand Down
123 changes: 76 additions & 47 deletions packages/native/test/native-css.test.js
@@ -1,105 +1,134 @@
import { css } from '@emotion/native'
import { StyleSheet } from 'react-native'

jest.mock('react-native')

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

describe('Emotion native css', () => {
test('basic', () => {
expect(css`
color: hotpink;
${{ backgroundColor: 'green' }};
`).toEqual({ color: 'hotpink', backgroundColor: 'green' })
expect(css({ color: 'green' })).toEqual({ color: 'green' })
expect(css([{ color: 'green' }, `background-color:yellow;`])).toEqual({
expect(
StyleSheet.flatten(css`
color: hotpink;
${{ backgroundColor: 'green' }};
`)
).toEqual({ color: 'hotpink', backgroundColor: 'green' })
expect(StyleSheet.flatten(css({ color: 'green' }))).toEqual({
color: 'green'
})
expect(
StyleSheet.flatten(css([{ color: 'green' }, `background-color:yellow;`]))
).toEqual({
color: 'green',
backgroundColor: 'yellow'
})
expect(css([{ color: 'green' }])).toEqual({ color: 'green' })
expect(StyleSheet.flatten(css([{ color: 'green' }]))).toEqual({
color: 'green'
})
})

test('order with string and object', () => {
// this test checks the keys instead of the objects
// because we care about the order of the keys
expect(
// $FlowFixMe
Object.keys(
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
StyleSheet.flatten(
css({ color: 'green' }, `background-color:yellow;`, { flex: 2 })
)
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
// $FlowFixMe
Object.keys(
css([
[{ color: 'green' }, `background-color:yellow;`],
{
flex: 2
}
])
StyleSheet.flatten(
css([
[{ color: 'green' }, `background-color:yellow;`],
{
flex: 2
}
])
)
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
// $FlowFixMe
Object.keys(
css([
{ color: 'green' },
[
`background-color:yellow;`,
{
flex: 2
}
]
])
StyleSheet.flatten(
css([
{ color: 'green' },
[
`background-color:yellow;`,
{
flex: 2
}
]
])
)
)
).toEqual(['color', 'backgroundColor', 'flex'])
expect(
// $FlowFixMe
Object.keys(
css([
{ color: 'green' },
[
{ flex: 8 },
`background-color:yellow;`,
[`flex-grow: 1;`, { flexDirection: 'row' }]
]
])
StyleSheet.flatten(
css([
{ color: 'green' },
[
{ flex: 8 },
`background-color:yellow;`,
[`flex-grow: 1;`, { flexDirection: 'row' }]
]
])
)
)
).toEqual(['color', 'flex', 'backgroundColor', 'flexGrow', 'flexDirection'])
})

it('allows function interpolations when this.mergedProps is defined', () => {
expect(
css.call({ thing: true }, props => ({
color: props.thing && 'hotpink'
}))
StyleSheet.flatten(
css.call({ thing: true }, props => ({
color: props.thing && 'hotpink'
}))
)
).toEqual({ color: 'hotpink' })
})

it('works with nested functions', () => {
expect(
css.call({ thing: true }, props => () => ({
color: props.thing && 'hotpink'
}))
StyleSheet.flatten(
css.call({ thing: true }, props => () => ({
color: props.thing && 'hotpink'
}))
)
).toEqual({ color: 'hotpink' })
})

it('works with functions in tagged template literals', () => {
expect(
css.call(
{},
...returnArguments`
StyleSheet.flatten(
css.call(
{},
...returnArguments`
color: ${() => 'hotpink'};
`
)
)
).toEqual({ color: 'hotpink' })
})

test('last arg falsy and string before that', () => {
expect(css('color:hotpink;', false)).toEqual({ color: 'hotpink' })
expect(StyleSheet.flatten(css('color:hotpink;', false))).toEqual({
color: 'hotpink'
})
})

test('falsy value in the middle', () => {
expect(
css`
StyleSheet.flatten(css`
color: ${false};
background-color: hotpink;
`
`)
).toEqual({ backgroundColor: 'hotpink' })
})

Expand All @@ -108,10 +137,10 @@ describe('Emotion native css', () => {
color: hotpink;
`
expect(
css`
StyleSheet.flatten(css`
background-color: green;
${firstStyle};
`
`)
).toEqual({ backgroundColor: 'green', color: 'hotpink' })
})

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

expect(styles).toEqual({ color: 'hotpink' })
expect(anotherStyles).toEqual({ fontSize: 10 })
expect(StyleSheet.flatten(styles)).toEqual({ color: 'hotpink' })
expect(StyleSheet.flatten(anotherStyles)).toEqual({ fontSize: 10 })
})
})
10 changes: 9 additions & 1 deletion packages/primitives-core/src/css.js
Expand Up @@ -7,6 +7,7 @@ import { interleave } from './utils'
// this is done so we don't create a new
// handleInterpolation function on every css call
let styles
let generated = {}
let buffer = ''
let lastType

Expand Down Expand Up @@ -102,7 +103,14 @@ export function createCss(StyleSheet: Object) {
buffer = prevBuffer
}

return StyleSheet.flatten(styles)
const hash = JSON.stringify(styles)
if (!generated[hash]) {
const styleSheet = StyleSheet.create({
generated: StyleSheet.flatten(styles)
})
generated[hash] = styleSheet.generated
}
return generated[hash]
}
}

Expand Down

0 comments on commit 139ea33

Please sign in to comment.