Sometimes we need to pass some actions to parent component. Lets take menu as example. If user clicks on menu item, that menu item style should change, other menu items styles should reset to normal. How will you create this?, we need to attach callback to child components from parent component dynamically. Lets do this

To Run Example Code

execute below commands
npm install
npm start
now open index.html in browser

Markup

Lets take a simple markup of menu. Observe below code. If user clicks on li element, then background color of that li item should be green and other li items background color should be normal grey color. Lets build our components
<ul>
  <li>List Item 1</li>
  <li>List Item 2</li>
  <li>List Item 3</li>
  <li>List Item 4</li>
  <li>List Item 5</li>
</ul>

ChildComponent.js

When user clicks on list item, parent callback function will be called with keyIndex
import React from 'react';
import classNames from 'classnames';

class ChildComponent extends React.Component {

  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.props.handleClick(this.props.keyIndex);
  }

  render() {
    return (
      <li className={classNames({'active':(this.props.selectedIndex === this.props.keyIndex)})} onClick={this.handleClick}>{this.props.children}</li>
    );
  }
}

ChildComponent.propTypes = {
   keyIndex:React.PropTypes.number
}

ChildComponent.defaultProps = {
}

export default ChildComponent;
This component creates li item.  

ParentComponent.js

This component creates ul item. Here in render function, We are cloning li items and attaching handleClick, keyIndex, selectedIndex  properties. Whenever user clicks on li item, handleClick callback will be called with keyIndex. Based on selectedIndex and keyIndex, background color of li item will change
import React from 'react';
import classNames from 'classnames';
import ValidComponentChildren from './ValidComponentChildren';

class ParentComponent extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      selectedIndex:-1
    }
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(keyIndex) {
    this.setState({
      selectedIndex:keyIndex
    });
  }

  render() {
    let keyIndexVal = 0;
    const items = ValidComponentChildren.map(this.props.children, child => {
      const childProps = child.props || {};
      keyIndexVal++;
      return React.cloneElement(child, {
        handleClick: this.handleClick,
        keyIndex:keyIndexVal,
        selectedIndex:this.state.selectedIndex
      }, childProps.children);
    });

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

ParentComponent.propTypes = {
}

ParentComponent.defaultProps = {
}

export default ParentComponent;

0 comments:

Blogroll

Popular Posts