小能豆

Reactjs map 函数无法渲染组件

javascript

这是我尝试呈现 createCardHotels 函数时出现的错误;但是,每次运行它时,什么都没有显示出来。如能得到任何帮助,我将不胜感激。

我使用 map 函数循环遍历数据,每次运行它时我都能在控制台上看到有数据。问题只是渲染部分。

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); 

阅读 37

收藏
2024-06-10

共1个答案

小能豆

您需要检查并调整代码中的一些内容,以确保功能createCardHotels正确呈现并显示酒店。

  1. 验证数据是否正确传递:确保hotelsprop 正确传递,且createCardHotels调用时不为空。您可以通过检查添加的控制台日志来执行此操作。
  2. 简化 getDerivedStateFromPropsgetDerivedStateFromProps :可以简化当前的实现以避免状态同步问题。
  3. 检查 CSS 和样式:确保您的 CSS 和样式不会导致渲染的元素不可见或位于视口之外。

更新的代码示例

这是您的组件的更新版本SelectHotel,可简化getDerivedStateFromProps并确保正确处理酒店数据:

import React, { Component } from 'react';
import { Container, Button, DropdownMenu, DropdownItem, Dropdown, DropdownToggle } from 'reactstrap';
import { Carousel } from 'react-responsive-carousel';
import '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';
import PropTypes from 'prop-types';

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

    this.state = {
      dropdownOpen: false,
    };

    this.toggleDropdown = this.toggleDropdown.bind(this);
  }

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

  createCardHotels = () => {
    const { hotels } = this.state;

    if (!hotels || hotels.length === 0) {
      return <p>No hotels available</p>;
    }

    return hotels.map((hotel) => (
      <div key={hotel._id} className="card">
        <div className="row ">
          <div className="col-md-4">
            <Carousel autoPlay infiniteLoop>
              {/* Assuming you have real images to display */}
              {hotel.images.map((image, index) => (
                <div key={index}>
                  <img src={image} alt={`Hotel ${hotel.name} Image ${index + 1}`} 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">{hotel.description}</p>
            </div>
          </div>
          <div className="col-md-3 price">
            <h1 className="reservation-price">${hotel.price}</h1>
            <Button style={cssStyles.buttonRoom} color="primary">Choose Hotel</Button>
          </div>
        </div>
      </div>
    ));
  }

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

  render() {
    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 />
        </Container>
      </div>
    );
  }
}

SelectHotel.propTypes = {
  hotels: PropTypes.array.isRequired,
};

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) => ({
  hotels: state.search.hotels,
});

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

主要变化:

  1. 简化getDerivedStateFromProps:这确保仅在发生变化时更新状态props.hotels
  2. 检查酒店数据:添加了登记入住功能createCardHotels,以处理没有酒店的情况。
  3. 添加了 PropTypes:确保hotelsprop 是一个数组。

确保您的酒店数据具有必要的属性(namedescriptionpriceimages)并且图片是有效的 URL。这应能确保您的组件在酒店数据存在时能够正确呈现。

2024-06-10