Randal Andrade Nunes
Randal Andrade Nunes

Reputation: 4864

How to pass props to styled component inside a loop

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Container } from './styles';

import { MdContentCopy, MdGroup, MdPerson, MdMovie, MdSettings } from 'react-icons/md';

const items = [
    {
        route: '/',
        icon: <MdContentCopy />,
        title: 'Orders',
    },
    {
        route: '/customers',
        icon: <MdGroup />,
        title: 'Customers',
    },
    {
        route: '/movies',
        icon: <MdMovie />,
        title: 'Movies',
    },
    {
        route: '/settings',
        icon: <MdSettings />,
        title: 'Settings',
    },
    {
        route: '/Profile',
        icon: <MdPerson />,
        title: 'Profile',
    },
];

class ItemList extends Component {
    state = {
        active: false,
    };
    render() {
        const { open, history } = this.props;
        const pathName = history.location.pathname;

        return (
            <Container open={open} active={this.state.active}> // PASSING ACTIVE PROPS TO STYLED COMPONENT
                {items.map((item, index) => {
                    if (item.route === pathName) this.setState({ active: true }); // THIS THROWS AN ERROR BECAUSE TOO MANY RE-RENDERS
                    return (
                        <Link to={item.route} key={index}>
                            {item.icon}
                            <span>{item.title}</span>
                        </Link>
                    );
                })}
            </Container>
        );
    }
}

export default ItemList;

I am trying to pass active props to my styled component (Container) inside the loop. I tried it with setState to trigger a re-render because if I just assign a variable (let active = false and if the if statement is true then active = true) it won't re-render the component and active will always be false. But setState inside a loop makes a ton of re-renders and throws a depth exceeded error. Any ideas of how I could do this?

Upvotes: 1

Views: 819

Answers (2)

vikram jeet singh
vikram jeet singh

Reputation: 3516

No need to setup the state in this use case (use item.route === pathName instead of this.state.active), just pass the active value as true or false to component, here is revised class mentioned below.

But in this use case matching one route will pass to the container as active= true.

class ItemList extends Component {
render() {
    const { open, history } = this.props;
    const pathName = history.location.pathname;

    const isActive = items.filter(item => item.route === pathName).length > 0;

    return (
        <Container open={open} active={isActive}> // PASSING ACTIVE PROPS TO STYLED COMPONENT
            {items.map((item, index) => {
                return (
                    <Link to={item.route} key={index}>
                        {item.icon}
                        <span>{item.title}</span>
                    </Link>
                );
            })}
        </Container>
    );
}

}

Upvotes: 1

Palash Kanti Bachar
Palash Kanti Bachar

Reputation: 616

Just I have copied your render method changes the concept here. Just I have checked the activeStatus in render method and pass it. For any state change render will be called and that time it will remake the activeStatus.

    render() {
    const { open, history } = this.props;
    const pathName = history.location.pathname;

    //code here to check the pathName
    let activeStatus = (items.filter(item => item.route == pathName) || []).length > 0 ? true : false;

    return (
      <Container open= { open } active = { activeStatus } > 
        {
          items.map((item, index) => {
            return (
              <Link to= { item.route } key = { index } >
                { item.icon }
                < span > { item.title } < /span>
                < /Link>
                        );
        })
  }
                </Container>
            );
        }

Upvotes: 0

Related Questions