问题
I need to slightly change the theme depending on the current section of the site.
It seems that MuiThemeProvider
only sets muiTheme
on load; but it needs to be updated when the props change.
How can this be done?
回答1:
You can try to put the theme in a wrapping component that keeps the theme in it's state. Using React's context this component exposes a function to child components to change the state.
import React, { Component } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import PropTypes from 'prop-types';
import theme from './theme';
import themeOther from './theme-other'
class Wrapper extends Component {
static childContextTypes = {
changeTheme: PropTypes.func
};
constructor(props) {
super(props);
this.state = {
muiTheme: getMuiTheme(theme)
};
}
getChildContext() {
return {changeTheme: this.changeTheme};
}
changeTheme = () => {
this.setState({
muiTheme: getMuiTheme(themeOther)
})
};
render() {
return (
<MuiThemeProvider muiTheme={this.state.muiTheme}>
{this.props.children}
</MuiThemeProvider>
)
}
}
export default Wrapper;
In some child component you can access the context and call the changeTheme function to set a different theme in the state. Make sure to include contextTypes else you can't access the function.
import React, { Component } from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import PropTypes from 'prop-types'
class ChildComponent extends Component {
static contextTypes = {
changeTheme: PropTypes.func
};
render() {
return (
<RaisedButton
primary
onTouchTap={this.context.changeTheme}
label="Change The Theme"
/>
);
}
}
export default ChildComponent;
In the root of your app just render the wrapper.
ReactDOM.render(
<Wrapper>
<App />
</Wrapper>,
document.getElementById('root')
);
EDIT: My first solution might have been abit too much. Since you are replacing the whole theme for the whole app. You can also use the MuiThemeProvider down the tree like so.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import inject from 'react-tap-event-plugin';
inject();
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import theme from './theme';
ReactDOM.render(
<MuiThemeProvider muiTheme={getMuiTheme(theme)}>
<App />
</MuiThemeProvider>,
document.getElementById('root')
);
In a child component you can just use the MuiThemeProvider again and override some properties. Note that these changes will reflect on all the children inside this MuiThemeProvider.
import React, { Component } from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import theme from './theme';
import { green800, green900 } from 'material-ui/styles/colors';
const localTheme = getMuiTheme(Object.assign({}, theme, {
palette: {
primary1Color: green800,
primary2Color: green900
}
}));
class App extends Component {
render() {
return (
<div>
<RaisedButton
primary
label="Click"
/>
<MuiThemeProvider muiTheme={localTheme}>
<RaisedButton
primary
label="This button is now green"
/>
</MuiThemeProvider>
</div>
);
}
}
export default App;
来源:https://stackoverflow.com/questions/43924536/muithemeprovider-how-to-use-different-themes-for-different-routes