MarkHughes88
MarkHughes88

Reputation: 669

Create a list from Array React JS

Im trying to create an array to store my category links and then display them however I'm getting nothing displaying in my DOM. Any help would be appreciated :)

import React from "react";
import { SidebarCategory } from './SidebarCategory';

class SidebarCategories extends React.Component {
    constructor() {
        super();
        this.state = {
            categories: []
        }
    }

    componentWillMount() {
        this.setState({categories: [
            {
                id: 1,
                icon: "icon",
                title: "Home",
            },
            {
                id: 2,
                icon: "icon",
                title: "Gallery",
            }
        ]});
    }

    render() {
        return (
            <ul className="sidebar__categories container-fluid">
                {this.state.categories.map(category => {
                    return (
                        <SidebarCategory key={category.id} title={category.title} />
                    )
                })};
            </ul>
        );
    }
}

export default SidebarCategories;

edit:

console error:

bundle.js:357 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of Sidebar. in Sidebar (created by App) in div (created by App) in App

sidebarCategory.js

import React from "react";

export class SidebarCategory extends React.Component {
    render() {
        const SidebarCategory = ({ title }) => {
          return (<div className="sidebarCategory">{title}</div>);
        }
    }
}

sidebar.js:

import React from "react";

import { SidebarCategories } from "./SidebarCategories";

export class Sidebar extends React.Component {
    render() {
        return (
            <div className="sidebar col-sm-2">
                <div className="row">
                    <div className="sidebar__header col">
                        <img alt="Logo" className="img-fluid sidebar__header__logo" src="../resources/img/logo-white.png" />
                        {'\u00A0'} <h4 className="i-block">Title</h4>
                    </div>
                </div>
                <div className="row">
                    <div className="sidebar__user container-fluid">
                        <div className="row">
                            <div className="col-sm-4">
                                <img alt="User DP" className="sidebar__user__img img-fluid rounded-circle" src="http://via.placeholder.com/100x100" />
                            </div>
                            <div className="col-sm-8">
                                <p><strong>Welcome</strong><br />
                                Mark Hughes</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="row">
                    <SidebarCategories />
                </div>
            </div>
        );
    }
}

index.js:

import React from "react";
import { render } from "react-dom";

import Sidebar from "./components/sidebar";
import Content from "./components/content";

class App extends React.Component {
    render() {
        return (
            <div className="row">
                <Sidebar />
                <Content />
            </div>
        );
    }
}

render(<App className="container-fluid"/>, window.document.getElementById("app"));

Upvotes: 0

Views: 35492

Answers (5)

Anas Tawfeek
Anas Tawfeek

Reputation: 109

I believe the issue is in your sidebarCategory.js, you created a stateless (arrow function) component inside a stateful component.

since its just a component that render data from its props you can use the stateless/arrow function alone like this.

    const SidebarCategory = ({ title }) => {
      return (<div className="sidebarCategory">{title}</div>);
    }
    export default SidebarCategory; // this way its exported as default component, import it without using curly brackets (import SidebarCategory from './SidebarCategory';
    // OR
    export SidebarCategory; // this way its exported as non-default component, import it using the curly brackets (import {SidebarCategory} from './SidebarCategory';

Upvotes: 0

Win
Win

Reputation: 2133

Try these: index.js

import React from "react";
import { render } from "react-dom";

import Sidebar from "./components/sidebar";
import Content from "./components/content";

class App extends React.Component {
    render() {
        return (
            <div className="row">
                <Sidebar />
                <Content />
            </div>
        );
    }
}

render(<App className="container-fluid"/>, document.getElementById("app"));

Sidebar.js

import React from "react";

import SidebarCategories from "./SidebarCategories";

class Sidebar extends React.Component {
    render() {
        return (
            <div className="sidebar col-sm-2">
                <div className="row">
                    <div className="sidebar__header col">
                        <img alt="Logo" className="img-fluid sidebar__header__logo" src="../resources/img/logo-white.png" />
                        {'\u00A0'} <h4 className="i-block">Title</h4>
                    </div>
                </div>
                <div className="row">
                    <div className="sidebar__user container-fluid">
                        <div className="row">
                            <div className="col-sm-4">
                                <img alt="User DP" className="sidebar__user__img img-fluid rounded-circle" src="http://via.placeholder.com/100x100" />
                            </div>
                            <div className="col-sm-8">
                                <p><strong>Welcome</strong><br />
                                Mark Hughes</p>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="row">
                    <SidebarCategories />
                </div>
            </div>
        );
    }
}

export default Sidebar;

SidebarCategory.js

import React from "react";

class SidebarCategory extends React.Component {
    render() {
        return (
                <div className="row">
                      <div className="col-sm-10">
                          {this.props.category.title}
                      </div>
                </div>
        );
    }
}

export default SidebarCategory;

SidebarCategories.js

import React from "react";
import SidebarCategory from './SidebarCategory';

class SidebarCategories extends React.Component {
    constructor() {
        super();
        this.state = {
            categories: []
        }
    }

    componentWillMount() {
        this.setState({categories: [
            {
                id: 1,
                title: "Home",
            },
            {
                id: 2,
                title: "Gallery",
            }
        ]});
    }

    render() {
        let list = this.state.categories.map((category) => {
          <li className="sidebar__category container-fluid" key={category.id}><SidebarCategory category={category} /></li>
        });

        return (
            <ul className="sidebar__categories container-fluid">
                {list}
            </ul>
        );
    }
}

export default SidebarCategories;

Upvotes: 0

Andrii Starusiev
Andrii Starusiev

Reputation: 7764

First in SidebarCategories

import {SidebarCategory}... //with curly braces

Second in Sidebar:

import SidebarCategories from "./SidebarCategories"; //without curly braces

See:

export class SidebarCategory //no default -> import {SidebarCategory} from...
export default SidebarCategories; //with default -> import SidebarCategories from ...

Upvotes: 1

Shubham
Shubham

Reputation: 738

import React from "react";
import SidebarCategory from './SidebarCategory';

class SidebarCategories extends React.Component {
    constructor() {
        super();
        this.state = {
            categories: []
        }
    }

    componentWillMount() {
        this.setState({categories: [
            {
                id: 1,
                title: "Home",
            },
            {
                id: 2,
                title: "Gallery",
            }
        ]});
    }

    render() {
        return (
            <ul className="sidebar__categories container-fluid">
                <SidebarCategory categories={this.state.categories} />
            </ul>
        );
    }
}

export default SidebarCategories;

And add this in your SidebarCategory file:-

import React from "react";

export class SidebarCategory extends React.Component {
    render() {
        return (
            <li className="sidebar__category container-fluid">
                <div className="row">
                      <div className="col-sm-10">
                          {this.props.categories.map((category, key) =>(
                            <span key={key}>{category.title}</span>
                          ))}
                      </div>
                </div>
            </li>
        );
    }
}

Upvotes: 3

Andy
Andy

Reputation: 63524

At the moment you're not iterating over your categories you have held in state, so the first thing is to map over them and provide your sub-component <SidebarCategory> the data it needs; a key from the category id, and the title.

render() {
  return (
    <ul className = "sidebar__categories container-fluid">
    {this.state.categories.map(category => {
      return (
        <SidebarCategory
          key={category.title}
          title={category.title}
        />
      )
    })}
    </ul>
  );
}

Then your <SidebarCategory> component should return a div (for example) the title of which is filled in from the props that you've provided it.

const SidebarCategory = ({ title }) => {
  return <div className="SidebarCategory">{title}</div>
}

export default SidebarCategory;

Upvotes: 1

Related Questions