Add "Theme" high order component and "theme" decorator#797
Add "Theme" high order component and "theme" decorator#797hai-cea merged 5 commits intomui:masterfrom SimonDegraeve:theme-decorator-hoc
Conversation
|
👍 HOC |
|
Done. |
Add "Theme" high order component and "theme" decorator
|
Thanks @SimonDegraeve |
|
Is there any way we can do this without having to do this weird construct: For example, in my app this results in this: I realise this is needed, because of this part of your code: Would it work (no React expert here, yet....) if we set them on the children directly? Instead of having to wrap it in a function. Something like https://github.com/martyjs/marty-lib/blob/e2640804254e796dd9ce03332e05239a2881c24d/modules/application/applicationContainer.js I think it would look like this: Then it would look nice if the result was something like: |
|
Guess what, I just tried it, and my guess worked: Or even: Now I got rid of the function in my app code's Should I create another PR to discuss and improve on this? |
|
Actually, I'll leave it here, I whipped this up for my case (without the decorator) which seems to work nicely: import React from 'react';
import { Styles } from 'material-ui';
import extend from './../../vendor/lodash/object/extend';
var ThemeManager = Styles.ThemeManager;
class Theme extends React.Component {
getChildContext() {
return {
muiTheme: this.themeManager.getCurrentTheme(),
muiThemeManager: this.themeManager
};
}
componentWillMount() {
this.themeManager = new ThemeManager();
if (this.props.theme) {
this.themeManager.setTheme(this.props.theme);
}
}
render() {
var _props = this.props;
var children = _props.children;
if (children) {
return React.createElement(children.type, extend({
muiTheme: this.themeManager.getCurrentTheme(),
muiThemeManager: this.themeManager
}, children.props));
}
}
}
Theme.displayName = 'Theme';
Theme.propTypes = {
theme: React.PropTypes.object
};
Theme.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
muiThemeManager: React.PropTypes.object.isRequired
};
export default Theme;And my app now has: import Theme from './util/theme-component';
import theme from './theme';
log('Running React.render with router.');
app.router.run(function (Handler, state) {
app.routeActions.activate(state);
React.render(
<Theme theme={theme}>
<ApplicationContainer app={app}>
<Handler {...state} />
</ApplicationContainer>
</Theme>,
document.body);
});Which actually makes me happy, since it's now a nice higher order component without having to depend on a function. |
|
Indeed I could use something like this. |
|
Ah yes, that looks even nicer, safer checking :) |
|
Hello, For example, App is my top-component import React from "react"
import { Theme } from "material-ui"
export default class App {
render() {
return (
<Theme>
{props => <div className="App">{this.props.children}</div>}
</Theme>
)
}
}And then deeper in the tree : import React from "react"
import { RaisedButton } from "material-ui"
export default class NestedComponent {
render() {
return (
<div className="NestedComponent">
<RaisedButton label="Awesome Button" />
</div>
)
}
} |
|
See here: as of now, context is only passed through the owner-ownee relationship (not the parent-child relationship). This is to be changed in a future version of react. I understand that the following construct: <Theme theme={myTheme}>
{props => // props contains the ThemeManager instance in "themeManager" property (also added to context)
<RaisedButton label='Super Button' primary={true}/>
}
</Theme>is used so that context from the Theme HOC can be passed down as owner-based context instead of parent-based context. Please correct me if my understanding is wrong. However, down the chain of hierarchy, I can still see some warnings pop up (that say that parent-based and owner-based contexts differ). Is this is a known issue? If so, is there an identified work-around? Hopefully, with React v0.14 (where contexts are passed only based on the parent-child relationship), this will be as simple as: <Theme theme={myTheme}>
<RaisedButton label='Super Button' primary={true}/>
</Theme> |
You can use it to set the theme and the context required by material-ui.
There is two ways to use it.