Reputation: 5260
I am trying React MobX on hover over a list item. Here is my code
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
is a observable.
The problem is that when mouse over one item, all of the items get the hover effect. What did I do wrong?
Upvotes: 0
Views: 1530
Reputation: 391
Do not set Component's props directly, set it on upper Component. or you could use state feature, and always use setState() to change state.
write an subcomponent to control the Button State
code below maybe help
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>
Upvotes: 2