2016-11-25 42 views
7

我知道如何从正在使用styled方式创建组件theme如何获取样式组件外的主题?

const StyledView = styled.View` 
    color: ${({ theme }) => theme.color}; 
`; 

但如何从正常成分获得或申请它不同性质?例如:

index.js

<ThemeProvider theme={{ color: 'red' }}> 
    <Main /> 
</ThemeProvider> 

main.js

<View> 
    <Card aCustomColorProperty={GET COLOR FROM THEME HERE} /> 
</View> 

注意如何,需要为主题的财产不叫style

回答

5

编辑:邻˚FV1.2,我拉的请求得到了合并,则可以使用 withTheme高阶组件是这样的:

import { withTheme } from 'styled-components' 

class MyComponent extends React.Component { 
    render() { 
    const { theme } = this.props 

    console.log('Current theme: ', theme); 
    // ... 
    } 
} 

export default withTheme(MyComponent) 

原帖如下

解决方案,我想出了通过现在:

创建一个高阶组件,将负责获得当前的我和通过为道具,以一个组件:

import React from 'react'; 
import { CHANNEL } from 'styled-components/lib/models/ThemeProvider'; 

export default Component => class extends React.Component { 
    static contextTypes = { 
    [CHANNEL]: React.PropTypes.func, 
    }; 

    state = { 
    theme: undefined, 
    }; 

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

    componentWillUnmount() { 
    if (typeof this.unsubscribe === 'function') this.unsubscribe(); 
    } 

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

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

然后,调用它,你需要访问theme组件上:

import Themable from './Themable.js' 

const Component = ({ theme }) => <Card color={theme.color} /> 

export default Themable(Component); 
+0

我试图使用'withTheme'像这样的功能组件: – aminimalanimal

+0

'出口常量圈= withTheme(({}题材)=>(<圈填充= {主题.circleColor} r =“40”/>))' – aminimalanimal

+0

虽然我得到一个错误,说它没有返回一个React节点,所以我假设'withProps'目前不能用于功能组件? – aminimalanimal

0

创建HOC是解决主题化的好办法。让我分享另一个想法,使用React的Context

上下文允许您将数据从父节点传递到它的所有子节点。 通过在组件定义中定义contextTypes,每个孩子可以选择访问context

比方说App.js是你的根。现在

import themingConfig from 'config/themes'; 
import i18nConfig from 'config/themes'; 
import ChildComponent from './ChildComponent'; 
import AnotherChild from './AnotherChild'; 

class App extends React.Component { 
    getChildContext() { 
     return { 
      theme: themingConfig, 
      i18n: i18nConfig, // I am just showing another common use case of context 
     } 
    } 

    render() { 
      return (
       <View> 
        <ChildComponent /> 
        <AnotherChild myText="hola world" /> 
       </View> 
     ); 
    } 
} 

App.childContextTypes = { 
    theme: React.PropTypes.object, 
    i18n: React.PropTypes.object 
}; 

export default App; 

我们`ChildComponent.js谁想要一些主题和国际化的字符串

class ChildComponent extends React.Component { 
    render() { 
     const { i18n, theme } = this.context; 

     return (
      <View style={theme.textBox}> 
       <Text style={theme.baseText}> 
        {i18n.someText} 
       </Text> 
      </View> 
     ); 
    } 
} 

ChildComponent.contextTypes = { 
    theme: React.PropTypes.object, 
    i18n: React.PropTypes.object 
}; 

export default ChildComponent; 

AnotherChild.js谁只想主题,但没有国际化。他可能是无状态的,以及:

const AnotherChild = (props, context) { 
    const { theme } = this.context; 
    return (<Text style={theme.baseText}>{props.myText}</Text>); 
} 

AnotherChild.propTypes = { 
    myText: React.PropTypes.string 
}; 

AnotherChild.contextTypes = { 
    theme: React.PropTypes.object 
}; 

export default AnotherChild; 
+0

上下文很棒,但我遇到了问题。由于上下文不会保证传播,所以树下的组件没有接收到新的上下文值:如果一个组件没有更新,它所有的子组件都不会更新。 –

+1

我刚刚发现这篇文章与上下文解释的问题,并提供了解决方案:https://medium.com/@mweststrate/how-to-safely-use-react-context-b7e343eff076 事实证明,这种解决方案什么风格的组件在内部做,在我的回答我订阅风格的组件上下文。看起来不错。你怎么看? –

+1

@BrunoLemos从我的角度来看,你的解决方案对我来说很不错!我们可能会添加类似核心的内容或直接公开CHANNEL并为此添加文档,您会介意提交代码问题吗?谢谢! – mxstbr