React主题未应用于子组件

时间:2017-05-27 10:21:49

标签: reactjs

这是我与React的第一次互动,代码如下:

header.jsx

import React from 'react';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import FlatButton from 'material-ui/FlatButton';
import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert';
import NavigationClose from 'material-ui/svg-icons/navigation/close';

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            logged: false
        };
    }

    render() {
        return (
            <AppBar title="Some title"
                iconElementLeft={<IconButton><NavigationClose /></IconButton>}
                iconElementRight={this.state.logged ? <Logged /> : <Login />} />
        );
    }
}

class Login extends React.Component {
    render() {
        return (
            <FlatButton label="Login" />
        );
    }
}

class Logged extends React.Component {
    render() {
        return (
            <IconMenu iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
                targetOrigin={{ horizontal: 'right', vertical: 'top' }}
                anchorOrigin={{ horizontal: 'right', vertical: 'top' }}>
                <MenuItem primaryText="Item1" />
                <MenuItem primaryText="Item2" />
                <MenuItem primaryText="Item2" />
            </IconMenu>
        );
    }
}

export default Header;


index.jsx

import React from 'react';
import ReactDOM from 'react-dom';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import lightBaseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';

import Header from './header.jsx';

import injectTapEventPlugin from 'react-tap-event-plugin';

injectTapEventPlugin();

class App extends React.Component {
  render() {
    return (
      <MuiThemeProvider muiTheme={getMuiTheme(lightBaseTheme)}>
        <div>
          <Header />
          <p> Hello React!</p>
        </div>
      </MuiThemeProvider>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

问题是主题仅应用于AppBar,而不是应用于其组件,这就是我所得到的: enter image description here

但是,如果我通过直接在AppBar组件中添加组件中的代码来更改Header组件,如下所示:

<AppBar title="Some title"
                iconElementLeft={<IconButton><NavigationClose /></IconButton>}
                iconElementRight={this.state.logged ? <Logged /> : <FlatButton label="Login" />} />

结果不同:

请您告诉我,为了将主题传播到子组件以及为什么它在第二种情况下有效,我缺少了什么?

提前致谢!

enter image description here

1 个答案:

答案 0 :(得分:0)

AppBar内部实现检查提供给iconElementRight属性的元素的类型。主题将自动提供&#39;只是显式匹配类型与某些预定义值的情况,例如 FlatButton

以下是内部工作原理(取自material-ui / AppBar源代码):

// around 239 line
if (iconElementRight) {
  var iconElementRightProps = {};

  switch (iconElementRight.type.muiName) {
    case 'IconMenu':
    case 'IconButton':
      var iconElemRightChildren = iconElementRight.props.children;
      var _iconButtonIconStyle = !(iconElemRightChildren && iconElemRightChildren.props && iconElemRightChildren.props.color) ? styles.iconButtonIconStyle : null;

      iconElementRightProps.iconStyle = (0, _simpleAssign2.default)({}, _iconButtonIconStyle, iconElementRight.props.iconStyle);
      break;

    case 'FlatButton':
      iconElementRightProps.style = (0, _simpleAssign2.default)({}, styles.flatButton, iconElementRight.props.style);
      break;

    default:
  }

如您所见,如果您提供一些自定义组件,则需要手动应用样式以匹配主题,例如使用上下文:

class Login extends React.Component {
  render() {
    return(
      <FlatButton style={{
        color: this.context.muiTheme.appBar.textColor
      }}/>
    )
  }
}

Login.contextTypes = {
  muiTheme: React.PropTypes.object.isRequired,
};