DEV Community

Discussion on: Keeping track of on/off states of React components

Collapse
 
kepta profile image
Kushan Joshi • Edited

Great article Kim, I just wanted to add another approach which works better in separating the concerns of managing the state and rendering the style.

Higher order components are great tool to solve this functionality. The function AddClick simply manages the state of one component hence avoiding the trouble of maintaining the state of all the children component in one single component. And the best part is, you can wrap any component with this HOC AddClick and it will get the isClicked prop, hence improving the usability of code.

Here is my alteration to your original code to make HOC work.

const Child = ({ id, isClicked }) => (
  <div
    className={isClicked ? `highlight` : ``}
  >{`ID ${id} --- I am a child element`}</div>
);

function AddClick(Comp) {
  return class HocClick extends Component {
    state = {
      clicked: null
    }
    onClick = i => {
      this.setState({
        clicked: !this.state.clicked
      });
    }
    render() {
      return <div onClick={this.onClick}>
        <Comp {...this.props} isClicked={this.state.clicked} />
      </div>;
    }
  };
}

const ClickableChild = AddClick(Child);

class App extends Component {
  render() {
    const items = [1, 2, 3, 4, 5].map((id, i) => {
      return (
        <ClickableChild id={id} key={id} />
      );
    });
    return (
      <div>{items}</div>
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Here is a working example of the app stackblitz.com/edit/react-o8qsku

Collapse
 
dance2die profile image
Sung M. Kim • Edited

Thank Kushan 👍,

That's a great way to abstract the click state functionality.

I love how each Child component gets to track its own clicked state (after wrapping it with AddClick HoC).

I've also gotten a feedback on Reddit and how someone already created a library react-on-off for such a scenario.

I believe that your HoC version is handy when good-enough is just good enough.

Collapse
 
barryblando profile image
Barry⚡ • Edited

Never forget to use prevState. 👍

  onClick = i => {
    this.setState(prevState => ({
      clicked: !prevState.clicked
    }));
  }
Collapse
 
vlackcoder profile image
Ghimmy

HI, thanks for this approach.
I've a little problem.... I want to be able to select only one item from the list of array and return other as false. Is there any workaround to this? Thanks