Matthew Matthew - 3 months ago 13
React JSX Question

How to select a group of children from the parent?

Say I have a

Parent
component which renders a set of
Child
components. When hovering one of those
Child
component, I wish to highlight (bg color) the
Child
components that belong in the same group.

See code below, each
Child
has a group property:

https://jsfiddle.net/69z2wepo/53442/

const Parent = React.createClass({
render() {
const rows = [];
let group = 1;
for (let i = 1; i <= 12; i++) {
rows.push(<Child key={i} id={i} group={group} />);

if (i % 3 === 0) {
group++;
}
}
return (
<ul>
{rows}
</ul>
);
}
});

const Child = React.createClass({
render() {
return (
<li className="child">id: {this.props.id} - group: {this.props.group}</li>
);
}
});

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


If I hover
Child
with id property of 6, how do I highlight all of the
Child
components which are in the same group, i.e. group 2 ?

NB: I'm new to React and sorry if the title is misleading.

Answer

I'd approach this with local state like so:

In a nutshell, we are generating a state variable for the current group on the parent. Then we give each child a proxy method it calls on onMouseEnter where it passes its group prop to the parent method. Then, each render compares the active group versus its own group and sets the active prop on the child. The child then checks its active prop to apply an active class. Obviously you can extend this behavior by a lot. Check out the Event System of React, here.

This fiddle is a very rudimentary example of how it works:

https://jsfiddle.net/69z2wepo/53444/

CSS

.active {
  background-color: yellow;
}

JS

const Parent = React.createClass({
    getInitialState() {
        return {
            group: null
        }
    },

    render() {
        const rows = [];
        let group = 1;

        for (let i = 1; i <= 12; i++) {
            const child = <Child 
              key={i}
              id={i}
              group={group} 
              hover={(group) => this.setState({ group })}
              active={group === this.state.group} />;

            rows.push(child);

            if (i % 3 === 0) {
                group++;
            }
        }

        return (
            <ul>
                {rows}
            </ul>
        );
    }
});

const Child = React.createClass({
    render() {
        return (
            <li 
              className={this.props.active && 'active'}
              onMouseEnter={() => this.props.hover(this.props.group)}
            >
                id: {this.props.id} - group: {this.props.group}
            </li>
        );
    }
});

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