Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: custom sheet #2677

Merged
merged 7 commits into from Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-dingos-design.md
@@ -0,0 +1,5 @@
---
'@emotion/react': patch
---

Change Global component to construct custom StyleSheet constructor. This is useful when cache.sheet is not the default implementation
41 changes: 40 additions & 1 deletion packages/react/__tests__/custom-cache.js
Expand Up @@ -2,7 +2,8 @@
/** @jsx jsx */
import 'test-utils/next-env'
import createCache from '@emotion/cache'
import { jsx, CacheProvider } from '@emotion/react'
import { jsx, CacheProvider, Global } from '@emotion/react'
import { StyleSheet } from '@emotion/sheet'
import renderer from 'react-test-renderer'

function stylisPlugin(element) {
Expand Down Expand Up @@ -38,3 +39,41 @@ test('with custom plugins', () => {
/>
`)
})

test('with custom sheet', () => {
// https://github.com/emotion-js/emotion/issues/2675
let cache = createCache({
key: 'test',
speedy: false
})

class GlobalSheet extends StyleSheet {
insert(rule) {
return super.insert('/** global */' + rule)
}
}
class MySheet extends StyleSheet {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed that you were constructing different sheet classes in the constructor of your custom implementation but perhaps that's not really needed. You can easily differentiate hashed/main and global sheets by just checking the options.key.endsWith('-global'). Based on that you can just assign some private property and branch the logic in the insert method. This way you only have to write a single StyleSheet class which might simplify your implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, I need to get the un-global version of the sheet so that's the easiest way, any way, thanks!

constructor(options) {
super(options)
if (Reflect.get(options.container, 'sheet')) {
return new GlobalSheet(options)
} else {
Reflect.set(options.container, 'sheet', this)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder - any particular reason why Reflect is used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To bypass the flow type check. sheet is not a property on the HTMLElement

}

insert(rule) {
super.insert(`/** ${this.key} */${rule}`)
}
}
cache.sheet = new MySheet({ key: 'test', container: document.head })

expect(
render(
<CacheProvider value={cache}>
<div css={{ display: 'flex', color: 'blue' }} />
<Global styles={{ body: { width: '0' } }} />
</CacheProvider>
)
).toMatchInlineSnapshot()
})
3 changes: 2 additions & 1 deletion packages/react/src/global.js
Expand Up @@ -91,7 +91,8 @@ export let Global: React.AbstractComponent<GlobalProps> =
useInsertionEffect(() => {
const key = `${cache.key}-global`

let sheet = new StyleSheet({
// use case of https://github.com/emotion-js/emotion/issues/2675
let sheet = new cache.sheet.constructor({
Jack-Works marked this conversation as resolved.
Show resolved Hide resolved
key,
nonce: cache.sheet.nonce,
container: cache.sheet.container,
Expand Down