2016-11-25 46 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