Skip to content

Commit

Permalink
Merge pull request #712 from styled-components/v2-hoist-static-hoc
Browse files Browse the repository at this point in the history
Hoist non-static properties on withTheme HOC
  • Loading branch information
kitten committed Apr 20, 2017
2 parents ade9ed9 + 73e1687 commit 871463b
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -20,6 +20,7 @@ All notable changes to this project will be documented in this file. If a contri
- Prevent leakage of the `innerRef` prop to wrapped child; under the hood it is converted into a normal React `ref`. (see [#592](https://github.com/styled-components/styled-components/issues/592))
- Pass `innerRef` through to wrapped Styled Components, so that it refers to the actual DOM node. (see [#629](https://github.com/styled-components/styled-components/issues/629))
- Added a dedicated Server-Side-Rendering API, with optimised rehydration on the client.
- Add hoisting static (non-React) properties for withTheme HOC, thanks to [@brunolemos](https://github.com/brunolemos). (See [#712](https://github.com/styled-components/styled-components/pull/712))

## [Unreleased]

Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -51,6 +51,7 @@
"buffer": "^5.0.3",
"css-to-react-native": "^2.0.3",
"fbjs": "^0.8.9",
"hoist-non-react-statics": "^1.2.0",
"inline-style-prefixer": "^2.0.5",
"is-function": "^1.0.1",
"is-plain-object": "^2.0.1",
Expand Down
57 changes: 36 additions & 21 deletions src/hoc/withTheme.js
Expand Up @@ -3,34 +3,49 @@

import React from 'react'
import PropTypes from 'prop-types'
import hoistStatics from 'hoist-non-react-statics'
import { CHANNEL } from '../models/ThemeProvider'

export default (Component: ReactClass<mixed>) => class extends React.Component {
static contextTypes = {
[CHANNEL]: PropTypes.func,
};
const wrapWithTheme = (Component: ReactClass<any>) => {
const componentName = (
Component.displayName ||
Component.name ||
'Component'
)

state: { theme?: ?Object } = {};
unsubscribe: () => void;
class WithTheme extends React.Component {
static displayName = `WithTheme(${componentName})`

componentWillMount() {
if (!this.context[CHANNEL]) {
throw new Error('[withTheme] Please use ThemeProvider to be able to use withTheme')
}
static contextTypes = {
[CHANNEL]: PropTypes.func,
};

const subscribe = this.context[CHANNEL]
this.unsubscribe = subscribe(theme => {
this.setState({ theme })
})
}
state: { theme?: ?Object } = {};
unsubscribe: () => void;

componentWillUnmount() {
if (typeof this.unsubscribe === 'function') this.unsubscribe()
}
componentWillMount() {
if (!this.context[CHANNEL]) {
throw new Error('[withTheme] Please use ThemeProvider to be able to use withTheme')
}

const subscribe = this.context[CHANNEL]
this.unsubscribe = subscribe(theme => {
this.setState({ theme })
})
}

render() {
const { theme } = this.state
componentWillUnmount() {
if (typeof this.unsubscribe === 'function') this.unsubscribe()
}

render() {
const { theme } = this.state

return <Component theme={theme} {...this.props} />
return <Component theme={theme} {...this.props} />
}
}

return hoistStatics(WithTheme, Component)
}

export default wrapWithTheme
11 changes: 11 additions & 0 deletions src/test/theme.test.js
Expand Up @@ -372,4 +372,15 @@ describe('theming', () => {

expectCSSMatches(`.sc-a { } .b { color: green; } `)
})

// https://github.com/styled-components/styled-components/issues/596
it('should hoist static properties when using withTheme', () => {
class MyComponent extends React.Component {
static myStaticProperty: boolean = true
}

const MyComponentWithTheme = withTheme(MyComponent)

expect(MyComponentWithTheme.myStaticProperty).toBe(true)
})
})
4 changes: 4 additions & 0 deletions yarn.lock
Expand Up @@ -2665,6 +2665,10 @@ hoek@2.x.x:
version "2.16.3"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"

hoist-non-react-statics@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"

home-or-tmp@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
Expand Down

0 comments on commit 871463b

Please sign in to comment.