react-with-styles
Advanced tools
Comparing version 4.0.0-alpha.3 to 4.0.0-alpha.4
## v4.0.0 | ||
- [breaking] Add @babel/runtime as a peer dependency (because of our dependency on babel-preset-airbnb) (@noratarano, [#229](https://github.com/airbnb/react-with-styles/pull/229)) | ||
- [new] Introduce the `useStyles` hook, which is still experimental. Use if you do not require performance optimizations for styles per component. (@noratarano, [#225](https://github.com/airbnb/react-with-styles/pull/225), [#221](https://github.com/airbnb/react-with-styles/pull/221)) | ||
- [new] Introduce the `useStyles` hook, which is still experimental. Use if you do not require performance optimizations for themed styles per component. (@noratarano, [#225](https://github.com/airbnb/react-with-styles/pull/225), [#221](https://github.com/airbnb/react-with-styles/pull/221)) | ||
- [new] Refactor `withStyles` to use a context-based implementation, rather than singletons in the `ThemedStyleSheet`. Works in a backward compatible way with the `ThemedStyleSheet` implementation. Note that this may break existing usages of the HOC if a wrapping component of a component using `withStyles` uses `contextTypes` and hoists `contextType` (usually accidentally). (@noratarano, [#225](https://github.com/airbnb/react-with-styles/pull/225/files), [#221](https://github.com/airbnb/react-with-styles/pull/221)) | ||
@@ -5,0 +5,0 @@ - [breaking] Drop support for node 6 (@noratarano, [#219](https://github.com/airbnb/react-with-styles/pull/219)) |
@@ -88,3 +88,3 @@ "use strict"; | ||
var stylesFnResultCacheMap = new Map(); // The function that wraps the provided component in a wrapper | ||
var stylesFnResultCacheMap = new WeakMap(); // The function that wraps the provided component in a wrapper | ||
// component that injects the withStyles props | ||
@@ -163,6 +163,11 @@ | ||
// once per theme for this component. | ||
var cachedResultForTheme = stylesFnResultCacheMap.get(theme); | ||
var isClient = typeof window !== 'undefined'; | ||
var cachedResultForTheme = isClient ? stylesFnResultCacheMap.get(theme) : null; | ||
var stylesFnResult = cachedResultForTheme || stylesFn(theme) || {}; | ||
stylesFnResultCacheMap.set(theme, stylesFnResult); // cache the result of stylesFn(theme) | ||
if (isClient) { | ||
// cache the result of stylesFn(theme) | ||
stylesFnResultCacheMap.set(theme, stylesFnResult); | ||
} | ||
return stylesFnResult; | ||
@@ -169,0 +174,0 @@ }; |
{ | ||
"name": "react-with-styles", | ||
"version": "4.0.0-alpha.3", | ||
"version": "4.0.0-alpha.4", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/withStyles.js", |
@@ -52,3 +52,3 @@ /* eslint-disable no-param-reassign, no-func-assign, class-methods-use-this */ | ||
/** Cache for storing the result of stylesFn(theme) for all themes. */ | ||
const stylesFnResultCacheMap = new Map(); | ||
const stylesFnResultCacheMap = new WeakMap(); | ||
@@ -113,5 +113,9 @@ // The function that wraps the provided component in a wrapper | ||
// once per theme for this component. | ||
const cachedResultForTheme = stylesFnResultCacheMap.get(theme); | ||
const isClient = typeof window !== 'undefined'; | ||
const cachedResultForTheme = isClient ? stylesFnResultCacheMap.get(theme) : null; | ||
const stylesFnResult = cachedResultForTheme || stylesFn(theme) || {}; | ||
stylesFnResultCacheMap.set(theme, stylesFnResult); // cache the result of stylesFn(theme) | ||
if (isClient) { | ||
// cache the result of stylesFn(theme) | ||
stylesFnResultCacheMap.set(theme, stylesFnResult); | ||
} | ||
return stylesFnResult; | ||
@@ -118,0 +122,0 @@ } |
@@ -14,2 +14,5 @@ /* eslint-disable no-unused-vars */ | ||
const describeIfClient = typeof window === 'undefined' ? describe.skip : describe; | ||
const describeIfServer = typeof window === 'undefined' ? describe : describe.skip; | ||
describe('withStyles', () => { | ||
@@ -467,29 +470,64 @@ let testTheme; | ||
it('re-calculates stylesFn(theme) at most once per theme', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount(<TestHelper />); | ||
expect(stylesFn).to.have.property('callCount', 1); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
wrapper.setProps({ stylesTheme: firstTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
expect(stylesFn.getCall(0).args[0]).to.equal(firstTheme); | ||
expect(stylesFn.getCall(1).args[0]).to.equal(secondTheme); | ||
describeIfClient('on the client', () => { | ||
it('re-calculates stylesFn(theme) at most once per theme', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount(<TestHelper />); | ||
expect(stylesFn).to.have.property('callCount', 1); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
wrapper.setProps({ stylesTheme: firstTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
expect(stylesFn.getCall(0).args[0]).to.equal(firstTheme); | ||
expect(stylesFn.getCall(1).args[0]).to.equal(secondTheme); | ||
}); | ||
it('re-calculates stylesFn(theme) per component per theme', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount( | ||
<div> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
</div>, | ||
); | ||
expect(stylesFn).to.have.property('callCount', 1); | ||
}); | ||
}); | ||
it('re-calculates stylesFn(theme) per component per theme', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount( | ||
<div> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
</div>, | ||
); | ||
expect(stylesFn).to.have.property('callCount', 1); | ||
describeIfServer('on the server', () => { | ||
it('re-calculates stylesFn(theme) on every render', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount(<TestHelper />); | ||
expect(stylesFn).to.have.property('callCount', 1); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 2); | ||
wrapper.setProps({ stylesTheme: firstTheme }); | ||
expect(stylesFn).to.have.property('callCount', 3); | ||
wrapper.setProps({ stylesTheme: secondTheme }); | ||
expect(stylesFn).to.have.property('callCount', 4); | ||
expect(stylesFn.getCall(0).args[0]).to.equal(firstTheme); | ||
expect(stylesFn.getCall(1).args[0]).to.equal(secondTheme); | ||
expect(stylesFn.getCall(3).args[0]).to.equal(firstTheme); | ||
expect(stylesFn.getCall(4).args[0]).to.equal(secondTheme); | ||
}); | ||
it('re-calculates stylesFn(theme) per component', () => { | ||
const TestHelper = makeTestHelper(); | ||
expect(stylesFn).to.have.property('callCount', 0); | ||
const wrapper = mount( | ||
<div> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
<TestHelper /> | ||
</div>, | ||
); | ||
expect(stylesFn).to.have.property('callCount', 4); | ||
}); | ||
}); | ||
@@ -496,0 +534,0 @@ }); |
147049
2564