MuiThemeProvider: How to use different themes for different routes?

随声附和 提交于 2019-12-11 01:47:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!