反应菜单项悬停

React menu item hover

我正在尝试将鼠标悬停在列表项上时使用 React MobX。这是我的代码

export default observer( 
class SidebarContent extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillMount() {
    this.props.store.fetchSources() 
  }  

  toggleHover(){
    this.props.store.hover = !this.props.store.hover;
  }

  getArticles(src) {
    this.props.store.fetchArticles(src); 
  }

 render() {
  const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
  const { sources, hover  } = this.props.store

    var linkStyle;
    if (this.props.store.hover) {
      linkStyle = {backgroundColor: 'black'}
    } else {
      linkStyle = {backgroundColor: 'white'}
    }

  const links = sources.map( (src,index) => (
    <a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
          <span style={linkStyle}  onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)}     >
            <img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
            <span className="side-news-item"> {src.name} </span>  
          </span>    
    </a>
  )) 
  return (
    <MaterialTitlePanel title="Menu" style={style1}>
      <div style={styles.content}>
        <div style={styles.divider} />
        {links}
      </div>
    </MaterialTitlePanel>
  );
  }
}
);
const styles = {
  sidebar: {
    width: 256,
    height: '100%',
  },
  sidebarLink: {
    display: 'block',
    padding: '16px 0px',
    color: '#757575',
    textDecoration: 'none',
  },
  divider: {
    margin: '8px 0',
    height: 1,
    backgroundColor: '#757575',
  },
  content: {
    padding: '16px',
    height: '100%',
    backgroundColor: 'white',
  },
};

this.props.store.hover 是可观察的。 问题是,当鼠标悬停在一个项目上时,所有项目都会获得悬停效果。我做错了什么?

不要直接设置Component的props,在上层Component上设置。 或者您可以使用状态功能,并始终使用 setState() 来更改状态。

写一个子组件来控制按钮状态

下面的代码可能有帮助

class SidebarContent extends React.Component {
  constructor(props) {
    super(props);
  }
  componentWillMount() {
    this.props.store.fetchSources() 
  }  

  getArticles(src) {
    this.props.store.fetchArticles(src); 
  }

 render() {


  const links = sources.map( (src,index) => <Button />); 
  return (
    <MaterialTitlePanel title="Menu" style={style1}>
      <div style={styles.content}>
        <div style={styles.divider} />
        {links}
      </div>
    </MaterialTitlePanel>
  );
  }
}

class Button extends React.Component {

  toggleHover(){
    this.setState({
      hover: !this.state.hover,
    });
  }


  render() {
    const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
    const { sources  } = this.props.store
    const { hover } = this.state;

    var linkStyle;
    if (hover) {
      linkStyle = {backgroundColor: 'black'}
    } else {
      linkStyle = {backgroundColor: 'white'}
    }
  
    return (
        <a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
          <span style={linkStyle}  onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)}     >
            <img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
            <span className="side-news-item"> {src.name} </span>  
          </span>    
    </a>
    );
  }

}


const styles = {
  sidebar: {
    width: 256,
    height: '100%',
  },
  sidebarLink: {
    display: 'block',
    padding: '16px 0px',
    color: '#757575',
    textDecoration: 'none',
  },
  divider: {
    margin: '8px 0',
    height: 1,
    backgroundColor: '#757575',
  },
  content: {
    padding: '16px',
    height: '100%',
    backgroundColor: 'white',
  },
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>