繁体   English   中英

重构类以在 React 中运行组件

[英]Refactor class to function components in React

尝试搜索术语和位置后的结果导致随机结果 我很难将这 3 个类组件转换为函数组件,类组件正在工作,我只是想将它们转换为学习目的。

API 调用:yelp.js

const { default: SearchBar } = require("../components/SearchBar/SearchBar");

const Yelp = {
    searchYelp(term, location) {
        return fetch(`/api/hello?term=${term}&location=${location}`)
        .then((response) => {
            // console.log(response)
            return response.json()
        }).then((jsonResponse) => {
            // console.log(jsonResponse)
            if (jsonResponse.businesses) {
                return jsonResponse.businesses.map((business) => {
                    return {
                        id: business.id,
                        imageSrc: business.image_url,
                        name: business.name,
                        address: business.location.address1,
                        city: business.location.city,
                        state: business.location.state,
                        zipCode: business.location.zip_code,
                        category: business.categories.title,
                        rating: business.rating,
                        reviewCount: business.review_count,
                    }
                })
            }
        })
    }
}

export default Yelp

Home 组件作为呈现 SearchBar 和 BusinessList 组件的函数:Home.js

import React, { useState } from "react";
import BusinessList from '../../../src/components/BusinessList/BusinessList';
import SearchBar from '../../../src/components/SearchBar/SearchBar';
import Yelp from '../../util/yelp';

const Home = (term, location) => {
    const [businesses, setBusinesses] = useState([]);

    const searchYelp = Yelp.searchYelp(term, location).then(businesses => {
        setBusinesses(businesses)
    })

    return (
        <>
            <SearchBar searchYelp={searchYelp} />
            <BusinessList business={businesses} />
        </>
    )
}

export default Home;

Home 组件作为一个类:Home.js

// import React from 'react';
// import BusinessList from '../../../src/components/BusinessList/BusinessList';
// import SearchBar from '../../../src/components/SearchBar/SearchBar';
// import Yelp from '../../util/yelp';

// class Home extends React.Component {
//     constructor() {
//         super();
//         this.state = {
//             businesses: [],
//         };

//         this.searchYelp = this.searchYelp.bind(this);
//     }

//     searchYelp(term, location, sortBy) {
//         Yelp.searchYelp(term, location, sortBy).then((businesses) => {
//             this.setState({ businesses: businesses })
//         })
//     }
//     render() {
//         return (
//             <>
//                 <SearchBar searchYelp={this.searchYelp} />
//                 <BusinessList businesses={this.state.businesses} />
//             </>
//         )
//     }
// }

// export default Home;

作为呈现业务组件的函数的 BusinessList 组件:BusinessList.js

import React, { useState } from "react";
import './BusinessList.css';
import Business from '../Business/Business';

function BusinessList(businesses) {
    console.log(businesses)
    return (
            <div className="BusinessList">
                {
                businesses.map(business => {
                    <Business key={business.id} business={business} />
                    })
                }
            </div>
    )
};

export default BusinessList;

作为类的 BusinessList 组件:BusinessList.js

// import React from 'react';
// import './BusinessList.css';
// import Business from '../Business/Business';

// class BusinessList extends React.Component {
//     constructor(props) {
//         super(props)
//         console.log(props.businesses)
//     }

//     render() {
//         return (
//             <div className="BusinessList">
//                 {
//                     this.props.businesses.map((business) => {
//                         return <Business key={business.id} business={business} />
//                     })
//                 }
//             </div>
//         )
//     }
// };

// export default BusinessList;

作为函数的业务组件:Business.js

import React from "react";
import './Business.css';

const Business = (business) => {
    return (
        <div className="Business">
            <div className="image-container">
                <img src={business.business.imageSrc} alt={business.imageSrc} />
            </div>
            <h2>{business.business.name}</h2>
            <div className="Business-information">
                <div className="Business-address">
                    <p>{business.business.address}</p>
                    <p>{business.business.city}&nbsp;{business.state}&nbsp;{business.zipCode}</p>
                </div>
                <div className="Business-reviews">
                    <h3>{business.business.category}</h3>
                    <h3 className="rating">{business.business.rating}</h3>
                    <p>{business.business.reviewCount} reviews</p>
                </div>
            </div>
        </div>
    )
};

export default Business;

作为一个类的业务组件:Business.js

// import React from "react";
// import './Business.css';

// class Business extends React.Component {
//     render() {
//         const { business } = this.props

//         return (
//             <div className="Business">
//                 <div className="image-container">
//                     <img src={business.imageSrc} alt={business.imageSrc} />
//                 </div>
//                 <h2>{business.name}</h2>
//                 <div className="Business-information">
//                     <div className="Business-address">
//                         <p>{business.address}</p>
//                         <p>{business.city}&nbsp;{business.state}&nbsp;{business.zipCode}</p>
//                     </div>
//                     <div className="Business-reviews">
//                         <h3>{business.category}</h3>
//                         <h3 className="rating">{business.rating}</h3>
//                         <p>{business.reviewCount} reviews</p>
//                     </div>
//                 </div>
//             </div>
//         )
//     }
// };

// export default Business;

编辑 ** 我尝试将 SearchBar 组件作为函数:SearchBar.js

import React, { useState, useEffect } from "react";
import './SearchBar.css';

const SearchBar = (props) => {
    const [term, setTerm] = useState('')
    const [location, setLocation] = useState('')
    const [sortBy, setSortBy] = useState('best_match')

    const sortByOptions = {
        'Best Match': 'best_match',
        'Highest Rated': 'rating',
        'Most Reviewed': 'review_count'
    };

    const handleSortByChange = () => {
        setSortBy(sortBy)
        // console.log(sortByOption)
        console.log(sortBy)
    }

    const renderSortByOptions = (sortByOptions) => {
        // console.log(Object.keys(sortByOptions))
        return Object.keys(sortByOptions).map(sortByOption => {
            let sortByOptionValue = sortByOptions[sortByOption]
            // console.log(sortByOptionValue)
            return <li
                className={sortBy === sortByOption ? 'active' : ''}
                onClick={handleSortByChange}
                key={sortByOptionValue}>
                {sortByOption}
            </li>;
        })
    }

    const handleTermChange = (event) => {
        setTerm(event.target.value)
    }

    const handleLocationChange = (event) => {
        setLocation(event.target.value)
    }

    const handleSearch = (event) => {
        event.preventDefault()
        props.searchYelp(term, location)
    }

    return (
        <div className="SearchBar">
            {props.searchYelp}
            <div className="SearchBar-sort-options">
                <ul>
                    {renderSortByOptions(sortByOptions)}
                </ul>
            </div>
            <div className="SearchBar-fields">
                <input
                    onChange={handleTermChange}
                    placeholder="Search Businesses"
                />
                <input
                    onChange={handleLocationChange}
                    placeholder="Where?"
                />
                <button className="SearchBar-submit" onClick={handleSearch}>Let's Go</button>
            </div>
        </div>
    )
}

export default SearchBar;

编辑** SearchBar 组件作为一个类:SearchBar.js

import React from 'react';
import './SearchBar.css';

class SearchBar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            term: '',
            location: '',
            sortBy: 'best_match'
        }

        this.handleTermChange = this.handleTermChange.bind(this)
        this.handleLocationChange = this.handleLocationChange.bind(this)
        this.handleSearch = this.handleSearch.bind(this)

        this.sortByOptions = {
            'Best Match': 'best_match',
            'Highest Rated': 'rating',
            'Most Reviewed': 'review_count'
        };
    }

    getSortByClass(sortByOption) {
        // console.log(sortByOption)
        if (this.state.sortBy === sortByOption) {
            return 'active'
        }
        return ''
    }

    handleSortByChange(sortByOption) {
        this.setState({
            sortBy: sortByOption
        })
    }

    handleTermChange(event) {
        this.setState({
            term: event.target.value
        })
    }

    handleLocationChange(event) {
        this.setState({
            location: event.target.value
        })
    }

    handleSearch(event) {
        this.props.searchYelp(this.state.term, this.state.location, this.state.sortBy)
        event.preventDefault()
    }

    renderSortByOptions() {
        return Object.keys(this.sortByOptions).map(sortByOption => {
            let sortByOptionValue = this.sortByOptions[sortByOption]
            console.log(sortByOptionValue)
            return <li
                onClick={this.handleSortByChange.bind(this, sortByOptionValue)}
                className={this.getSortByClass(sortByOptionValue)}
                key={sortByOptionValue}>
                {sortByOption}
            </li>;
        })
    }

    render() {
        return (
            <div className="SearchBar">
                {this.searchYelp}
                <div className="SearchBar-sort-options">
                    <ul>
                        {this.renderSortByOptions()}
                    </ul>
                </div>
                <div className="SearchBar-fields">
                    <input onChange={this.handleTermChange} placeholder="Search Businesses" />
                    <input onChange={this.handleLocationChange} placeholder="Where?" />
                    <button className="SearchBar-submit" onClick={this.handleSearch}>Let's Go</button>
                </div>
            </div>
        )
    }
};

export default SearchBar;

我不断收到错误“无法读取未定义的属性(读取‘地图’)或错误“Businesses.map 不是函数”

我也有点困惑,为什么在我的最终业务组件中将所有内容都转换为功能组件以显示内容时,我需要将内容作为 business.business.imageSrc 传递,而不仅仅是 business.imageSrc

BusinessList接收props ,一个包含传入的 props 的对象。

函数参数要么需要解构它:

function BusinessList({ businesses }) { ... }

或者从props对象引用它:

function BusinessList(props) {
  console.log(props.businesses)
  // ...
}

首先在Home searchYelp应该声明为一个函数,以便它可以作为回调传递给SearchBar组件。

const Home = () => {
  const [businesses, setBusinesses] = useState([]);

  const searchYelp = (term, location) => {
    Yelp.searchYelp(term, location)
      .then(businesses => {
        setBusinesses(businesses);
      });
  };

  return (
    <>
      <SearchBar searchYelp={searchYelp} />
      <BusinessList business={businesses} />
    </>
  )
};

然后在BusinessList您需要访问传递的business道具。 您当前的代码正在命名道具对象businesses ,然后尝试映射它。 它可以是businesses.business.map ,但按照惯例,我们将 props 对象命名为props或简单地解构您想要使用的 props。 您还需要返回您要映射到的Business组件。

function BusinessList({ business }) {
  return (
    <div className="BusinessList">
      {business.map(business => {
        return <Business key={business.id} business={business} />;
      })}
    </div>
  )
};

Business组件中的道具对象名称相同的问题。

const Business = (props) => {
  return (
    <div className="Business">
      <div className="image-container">
        <img src={props.business.imageSrc} alt={props.business.imageSrc} />
      </div>
      <h2>{props.business.name}</h2>
      <div className="Business-information">
        <div className="Business-address">
          <p>{props.business.address}</p>
          <p>{props.business.city}&nbsp;{props.business.state}&nbsp;{business.zipCode}</p>
        </div>
        <div className="Business-reviews">
          <h3>{props.business.category}</h3>
          <h3 className="rating">{props.business.rating}</h3>
          <p>{props.business.reviewCount} reviews</p>
        </div>
      </div>
    </div>
  )
};

几点注意事项:

  • 现在Yelp.searchYelp返回Promise<any[] | undefined> Promise<any[] | undefined> ,即undefined是消费可能获得的合法值。 由您决定当businesses未定义时setBusinesses(businesses)是否有用,但在这种情况下,请处理它。 否则默认为空数组, setBusinesses(businesses ?? [])或抛出错误。
  • 不要在渲染阶段运行副作用,即在useEffect调用 api:
React.useEffect(() => {
    const searchYelp = Yelp.searchYelp(term, location).then(businesses => {
        setBusinesses(businesses ?? [])
    })
}, [term, location])
  • 最后, const Business = (business) => {这里business实际上是 props 对象。 您可以简单地对其进行解构const Business = ({ business }) => {以直接获取值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM