Le Tuan Anh
Le Tuan Anh

Reputation: 73

Reactjs map function does not render the component

This is the error I am trying to render the createCardHotels function;however, whenever I run it, nothing shows up. Any help will be appreciated.

I used map function to loop through the data and whenever I run it I can see on the console that there is the data. The problem is just the rendering part.

import React, {Component} from 'react';
import {Container, Button, DropdownMenu, DropdownItem, Dropdown, DropdownToggle} from 'reactstrap';
import {Carousel} from 'react-responsive-carousel';
import styles from 'react-responsive-carousel/lib/styles/carousel.min.css';
import './selectHotel.css'
import Scroll from '../ScrollUp';
import {search} from '../../actions/search';
import {connect} from 'react-redux';

class SelectHotel extends Component{
  constructor(props){
      super(props);

      this.state={
          dropdownOpen: false,
          hotels: []
      };
      this.toggleDropdown = this.toggleDropdown.bind(this);
  }

  static getDerivedStateFromProps(state, props){
      if(props.hotels !== state.hotels)
        return{
            ...state,
            hotels: props.hotels
        }
        return null;
  }

  createCardHotels = () => {
     return this.state.hotels.map((hotel) => {
        return(
            <div key={hotel._id} className="card">
                <div className="row ">
                    <div className="col-md-4">
                        <Carousel autoPlay infiniteLoop>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                            <div>
                                <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>
                            </div>
                        </Carousel>
                    </div>
                    <div className="col-md-5 px-3">
                        <div className="card-block px-3">
                            <h3 className="card-title">{hotel.name}</h3> 
                            <p className="card-text">description</p>
                        </div>
                    </div>
                    <div className="col-md-3 price">
                        <h1 className="reservation-price">$Price</h1>
                        <Button style={cssStyles.buttonRoom} bsStyle="primary">Choose Hotel</Button>
                    </div>
                </div>  
            </div>
            )}
        )
    }

  toggleDropdown() {
    this.setState(prevState => ({
      dropdownOpen: !prevState.dropdownOpen
    }));
  }

  render(){
      console.log(this.state)
      console.log(this.props)
    return(
        <div>
            <Container>
            <Scroll/>
            <div>
            <Dropdown className = 'sortbutton' size="lg" isOpen={this.state.dropdownOpen} toggle={this.toggleDropdown}>
              <DropdownToggle style={{backgroundColor: "white", borderColor: "grey" , color: "black"}} caret>
                  Sort By:
              </DropdownToggle>

              <DropdownMenu>
                <DropdownItem onClick={()=>{this.setSort("low");}}>
                  Price: Low to High
                </DropdownItem>

                <DropdownItem divider />

                <DropdownItem onClick={()=>{this.setSort("high");}}>
                  Price: High to Low
                </DropdownItem>
              </DropdownMenu>
            </Dropdown>
            </div>
            {this.createCardHotels()}
            <br></br>
            </Container>
        </div>
    );
  }
}

const cssStyles = {
    buttonRoom:{
        backgroundColor: '#156bc1',
        border: '1px solid #156bc1',
        alignItems: 'left',
        boxShadow: 'inset 0 -2px 0 #063665',
        paddingLeft: '2rem',
        paddingRight: '2rem',
        fontSize: '0.8rem'
    }
  }

  const mapStatetoProps = state => {
    return {
        hotels: state.search.hotels
    };
  }

  export default connect(mapStatetoProps, {search})(SelectHotel); 

EDIT: This is the image from console after I put console.log(this.state), console.log(this.props), it seems like there is data in this.props and not in this.state

Upvotes: 2

Views: 866

Answers (3)

KushalSeth
KushalSeth

Reputation: 4629

I have struggled more than an hour to figure out this simple mistake.

Let me tell you with simple example..

Map works in 2 format.

  1. If you are using curly braces => { return ..} then it should return.
   <div>
      {items.map((item) => {
        return <div key={item.card.info.id}>{item.card.info.id}</div>;
      })}
   </div>
  1. Otherwise use oval brackets => ( .. ) without return
    <div>
      {items.map((item) => (
        <div key={item.card.info.id}>{item.card.info.id}</div>
      ))}
    </div>

Upvotes: 0

Сould you please show your building file. May be a problem with file-loader.

Upvotes: 0

Hemadri Dasari
Hemadri Dasari

Reputation: 33974

The issue is with add class names to JSX elements. You are using class to apply css styles with class names but class is reserved for creating class components in React so you need to use className

Wherever you see class on jsx elements change it to className

Also never forget to add key to the top parent jsx element when you render them in loop. If you have unique from data then set id from data as a key like I did below else use index as key

Change

  return this.state.hotels.map((hotel) => {
    return(
        <div class="card">
         ........

To

  return this.state.hotels.map((hotel) => {
    return(
        <div key={hotel.id} className="card">
         .......

Also

Change

   <h1 className="reservation-price">$Price</h1>

To

   <h1 className="reservation-price">{"$Price"}</h1>

For images you need to use require or import

Change

  <img src="https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400" className="w-100"/>

To

  <img src={require("https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400")} className="w-100"/>

Do the same for other images as well

Or import it like

  import text from "https://placeholdit.imgix.net/~text?txtsize=38&txt=400%C3%97400&w=400&h=400";

  <img src={text} className="w-100"/>

Upvotes: 2

Related Questions