Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access the child component prop inside the parent component

I'm facing a problem there is a styled component named Breadcrumb but that component depends upon 1 separate styled-components i.e BreadcrumbItem. Both components have different props.

BreadcrumbItem.js:

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const propTypes = {
  /** Active the current BreadcrumbItem. */
  active: PropTypes.bool,
  /** Additional classes. */
  className: PropTypes.string
};



const AbstractBreadcrumbItem = (props) => {
  const { className, active, ...attributes } = props;

  return <li {...attributes} className={className} />;
};

AbstractBreadcrumbItem.propTypes = propTypes;

const BreadcrumbItem = styled(AbstractBreadcrumbItem)``;

BreadcrumbItem.propTypes = propTypes;

export default BreadcrumbItem;

Breadcrumb.js:

import React from "react";
import styled from "styled-components";
import PropTypes from "prop-types";

const propTypes = {
  /** Additional classes. */
  className: PropTypes.string,
  /** Primary content. */
  children: PropTypes.node,
  /** Custom separator */
  separator: PropTypes.string,
  /** Change the look and feel of the BreadcrumbItem. */
  scheme: PropTypes.oneOf(["red", "purple"]).isRequired
};

const defaultProps = {
  scheme: "red",
  separator: "/"
};

const AbstractBreadcrumb = props => {
  const { className, children, separator, scheme, ...attributes } = props;

  return (
    <ul {...attributes} className={className}>
      {children}
    </ul>
  );
};

AbstractBreadcrumb.propTypes = propTypes;
AbstractBreadcrumb.defaultProps = defaultProps;

const Breadcrumb = styled(AbstractBreadcrumb)`

              display: flex;
              flex-wrap: wrap;
              padding: 18px 26px;
              margin-bottom: 1rem;
              list-style: none;
              background-color: #fbfbfb;
              border-radius: 4px;


              li + li:before {
                content: "${props => props.separator}";
              }

              li + li {
                padding-left: 8px;
            }

              li + li::before {
              display: inline-block;
              padding-right: 0.5rem;
            }

            li a {
               font-size: 14px;
               transition: color .4s linear;
               color: ${props => (props.scheme === "red" ? "red" : "purple")};
               &:hover {
                color: black;
               }
            }
`;

Breadcrumb.propTypes = propTypes;
Breadcrumb.defaultProps = defaultProps;

export default Breadcrumb;

This is the main markup to create the Breadcrumb.

App.js:

import React from 'react';
import Breadcrumb from './Breadcrumb';
import BreadcrumbItem from './BreadcrumbItem';

export default function App() {
  return (
    <div className="App">
      <Breadcrumb scheme="red">
        <BreadcrumbItem>
          <a href="/">Home</a>
        </BreadcrumbItem>
        <BreadcrumbItem>
          <a href="/">Shop</a>
        </BreadcrumbItem>
        <BreadcrumbItem active>
          <a href="/">Product</a>
        </BreadcrumbItem>
      </Breadcrumb>
    </div>
  );
}

What problem I'm facing is I want to use the active prop of the BreadcrumbItem component inside the parent Breadcrumb component to change the look and feel of the item according to the scheme.

I found the first way which is to add the BreadcrumbItem styles inside the component itself and use something like this ${props => props.active ? css`` : css``}. But Is there a way in styled-component to access the child component prop inside the Parent component?

Please answer the question in the context of styled-components.

Live link: Codesandbox

like image 593
Ven Nilson Avatar asked May 22 '20 10:05

Ven Nilson


People also ask

How do you access the child component state in the parent component?

In React we can access the child's state using Refs. we will assign a Refs for the child component in the parent component. then using Refs we can access the child's state. Creating Refs Refs are created using React.

Can we pass props from child to parent component?

To pass data from a child component to its parent, we can call a parent function from the child component with arguments. The parent function can be passed down to the child as a prop, and the function arguments are the data that the parent will receive.


Video Answer


1 Answers

I'd suggest to move the styling of list item, i.e. <li>, to its own component, i.e. BreadcrumbItem. In this scenario you won't need to access the state of child component instead you'll be handling active state in <li> styles. And it'll look more cleaner and separation of concern (which React recommends) will be there.

[EDIT]: Sample code to access props of children

const List = ({ children }) => {
  return (
    <ul>
      {React.Children.map(children, x => {
        console.log(x.props); // get props of children

        return x;
      })}
    </ul>
  );
};

const Item = ({ children }) => <li>{children}</li>;

export default function App() {
  return (
    <List>
      <Item>Hello</Item>
      <Item active>HI</Item>
    </List>
  );
}
like image 188
Muhammad Ali Avatar answered Jan 04 '23 13:01

Muhammad Ali