loading...
Cover image for Advanced Reactjs

Advanced Reactjs

saigowthamr profile image Sai gowtham Updated on ・2 min read

Today we learn something new and advanced in Reactjs we all know in Reactjs props are used to communicate with the other components.

Now we learn something different called Compound Components in React using some top-level apis.

1.React.Children.map
2.React.cloneElement()

Our final output should like the below image.

React-Accordion

Accordion Component code

<Accordion>
        <Heading>Heading 1</Heading>
        <Text>
          You've gotta dance like there's nobody watching, Love like you'll
          never be hurt, Sing like there's nobody listening, And live like it's
          heaven on earth.” ― William W. Purkey
        </Text>
        <Heading>Heading 2</Heading>

        <Text>
          “Don’t walk in front of me… I may not follow Don’t walk behind me… I
          may not lead Walk beside me… just be my friend” ― Albert Camus
        </Text>
        <Heading>Heading 3</Heading>

        <Text>
          “Darkness cannot drive out darkness: only light can do that. Hate
          cannot drive out hate: only love can do that.” ― Martin Luther King
          Jr., A Testament of Hope: The Essential Writings and Speeches
        </Text>
        <Heading>Heading 4</Heading>

        <Text>
          Mauris mauris ante, blandit et, ultrices a, suscipit eget, quam.
          Integer ut neque. Vivamus nisi metus, molestie vel, gravida in,
          condimentum sit amet, nunc. Nam a nibh. Donec suscipit eros. Nam mi.
          Proin viverra leo ut odio. Curabitur malesuada. Vestibulum a velit eu
          ante scelerisque vulputate.
        </Text>
        <Heading>Heading 5</Heading>
        <Text>
          “I believe that everything happens for a reason. People change so that
          you can learn to let go, things go wrong so that you appreciate them
          when they're right, you believe lies so you eventually learn to trust
          no one but yourself, and sometimes good things fall apart so better
          things can fall together.  Marilyn Monroe
        </Text>
      </Accordion>

Now let's get into the logic in above code Accordion component is holding the different types of children example Heading, Text.

Accordion Component implementation.


class Accordion extends React.Component {
  state = {
    active: -1
  };

  onShow = i => {
    this.setState({
      active: i
    });
  };
  render() {
    const children = React.Children.map(this.props.children, (child, i) => {
      return React.cloneElement(child, {
          heading: this.state.active  === i,
          text: this.state.active + 1 === i,
          onShow: () => this.onShow(i)
      });
    });

    return <div className="accordion">{children}</div>;
  }
}

what above code does is instead of returning the children we are mapping the children using React.Children.map and cloning the child by passing some state to the Children it means we are passing state down to the children.

Heading Component.

class Heading extends React. Component {
  render() {
    const { heading, onShow, children } = this.props;

    return (
      <h2 className={heading ? "active" : "normal"} onClick={onShow}>
        {children}
      </h2>
    );
  }
}

Text Component

class Text extends React.Component {
  contentBox = () => {
    if (!this.props.text) {
      return null;
    } else {
      return (
        <div className="content-box">
          <p className="text">{this.props.children}</p>
        </div>
      );
    }
  };

  render() {
    return this.contentBox();
  }
}

Other example

Have you seen there is no state present inside the Text or Heading components.

Hope you guys enjoyed....

Demo url

Code Repository

Posted on Jun 29 '18 by:

saigowthamr profile

Sai gowtham

@saigowthamr

JavaScript developer, Blogger & Serverless

Discussion

markdown guide
 

How is this any different than passing the same data via props?

I don't understand the benefit of doing it this way instead of doing it the "proper" way via properties.

If anything, you are making a simple concept harder to understand and read.

Also, aren't you dropping performance by cloning the elements on every render call?

 

There is only single state present in the entire code and also the state is accessible to all child components if I need to change the state from the heading component all components are updated with updated state.

If i need to render the Text component above and heading component below still it works without changing any code in the text component or heading component.