Search code examples
jsonreactjsexpresscreate-react-app

In react component how I can map the json property which is array of object?


Actually, I am new in react development and I want to show product page with it's summery but in JSON I have arrays of an object (maybe, shown in code). When I try to use .map I got an error like the prop is undefined.

I have JSON object like below

{
      "id": 794,
      "name": "Pellentesque habitant morbi",
      "description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n",
      "short_description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n",
      "sku": "1000",
      "price": "200",
      "categories": [
        {
          "name": "Best Seller"
        }
      ],
      "regular_price": "21.99",
      "tags": [
        {"name" : "Books Online"},
        {"name" : "Ebooks"},
      ],
      "images": [
        {
          "src": "https://example.com/wp-content/uploads/2017/03/T_2_front-4.jpg",
        },
        {
          "src": "https://example.com/wp-content/uploads/2017/03/T_2_back-2.jpg",
        }
      ],
      "author": "Mo. Ra. Walambe"
    }

In my component render method, I am doing this

rendor(){
 var tags = [];
 const prodSum = this.props.product;
 tags = prodSum.tags.map( (tag) => {
     return <li>{tag.name}</li>;
 });

 return(
         <h1 className="product_title">{prodSum.name}</h1>
         <span className="posted_in">
            Categories: <ul>{tags}</ul>
         </span>
 );
};

error is : prodSum.tags is undefined where I am able to show prodSum.name

Why it is not working with array.

I want to display the list of tags


Solution

  • As a blind suggestion as I do in my comment, you can conditionally render your component.

    const product = {
      id: "794",
      name: "Pellentesque habitant morbi",
      description:
        "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n",
      short_description:
        "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n",
      sku: "1000",
      price: "200",
      categories: [
        {
          name: "Best Seller"
        }
      ],
      regular_price: "21.99",
      tags: [
        {
          name: "Books Online"
        },
        {
          name: "Ebooks"
        }
      ],
      images: [
        {
          src: "https://example.com/wp-content/uploads/2017/03/T_2_front-4.jpg"
        },
        {
          src: "https://example.com/wp-content/uploads/2017/03/T_2_back-2.jpg"
        }
      ],
      author: "Mo. Ra. Walambe"
    };
    
    function fakeApi() {
      return new Promise(resolve => setTimeout(() => resolve(product), 2000));
    }
    
    class App extends React.Component {
      state = {
        product: null,
      };
    
      componentDidMount() {
        fakeApi().then(product => this.setState({ product }));
      }
    
      render() {
        return (
          <div>
            <Product product={this.state.product} />
          </div>
        );
      }
    }
    
    function Product(props) {
      const { product } = props;
      if (!product) return <div>Getting the product...</div>;
      
      const tags = product.tags.map(tag => {
        return <li>{tag.name}</li>;
      });
    
      return (
        <div>
          <h1 className="product_title">{product.name}</h1>
          <span className="posted_in">
            Categories: <ul>{tags}</ul>
          </span>
        </div>
      );
    }
    
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    <div id="root" />

    Do not think about the fakeApi part, I'm just simulating the fetch part there. I'm not sure how do you initialize the product state in the parent component but as you can see I'm doing it as null. So I can check its existence in the child component. If no product yet I'm rendering a piece of temporary information. After fetching the product child component is rerendered and return the product information.

    As you can see in the comments there can be other scenarios. For example, you can set the initial state to {} and check for its properties' existence, like tags or set them to empty values like [] for the first render.

    Using conditional rendering is common usage. React can deal with undefined values, there isn't any problem with that. This is why prodSum.name is not a problem, since it is undefined. But Javascript can't deal something like undefined.someValue. Because you are trying to get someValue from undefined and this is not possible. prodSum.tags[0].name is undefined.name here.