You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js(Express)中获取查询参数并在React前端实现搜索过滤

问题详情

技术栈

  • node.js(express) 服务端
  • React 前端

组件文件夹结构

|__src
|  |__components
|     |__App
|     |   |__App.js
|     |   |__App.css
|     |__Business
|     |   |__Business.js
|     |   |__Business.css
|     |__BusinessList
|     |   |__BusinessList.js
|     |   |__BusinessList.css
|     |__SearchBar
|         |__img
|         |__SearchBar.js
|        |__SearchBar.css
|__util
   |__yelp.js

预期效果

用户在「Search Businesses」输入框输入搜索词、在「Where?」输入框输入位置,点击「Let's go」按钮后,可以根据输入的分类(例如:Pizza)和位置(例如:Denver)过滤返回的商家列表。

当前实现逻辑

点击「Let's Go」按钮时会调用从yelp.js导入到App.js的searchYelp函数,yelp.js中的searchYelp函数会请求express服务的/api/hello端点,由express服务调用Yelp第三方API获取数据。

当前问题

过滤逻辑不生效,点击「Let's Go」按钮后仅返回随机商家列表,已编写的过滤代码没有正确接入。

相关代码

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

App.js

import React from 'react';
import BusinessList from '../BusinessList/BusinessList';
import SearchBar from '../SearchBar/SearchBar';
import Yelp from '../../util/yelp';
import './App.css';

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

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

  searchYelp(term) {
    Yelp.searchYelp(term).then((businesses) => {
      this.setState({ businesses: businesses })
    })
  }
  render() {
    return (
      <div className="App">
        <SearchBar searchYelp={this.searchYelp} />
        <BusinessList businesses={this.state.businesses} />
      </div>
    )
  }
}

export default App;

Yelp.js

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

const Yelp = {
    searchYelp(term) {
    return fetch('/api/hello/:term')
        .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

服务端Server.js

const express = require('express');
const axios = require('axios');
require('dotenv').config();
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();
app.use(cors());
const port = process.env.PORT || 5000;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const apiKey = process.env.APIKEY

app.get('/api/hello/:term', (req, res) => {
    const term = req.params.term
    const config = {
        method: 'get',
        url: 'https://api.yelp.com/v3/businesses/search?term=${term}&location=${location}',
        headers: {
            'Authorization': `Bearer ${apiKey}`
        }
    };

    axios(config)
        .then(function (response) {
            return JSON.stringify(response.data, null, 2)
        }) 
        .then(function (jsonResponse) {
            res.send(jsonResponse)
        }) 
        .catch(function (error) {
            console.log(error);
        });
});

app.listen(port, () => console.log(`Listening on port ${port}`));

应用截图

网页应用截图


修复方案

1. 修改App.js的searchYelp方法

原方法只接收了term参数,没有接收SearchBar传递的location和sortBy参数,需要补全参数并传递给Yelp的searchYelp方法:

searchYelp(term, location, sortBy) {
  Yelp.searchYelp(term, location).then((businesses) => {
    this.setState({ businesses: businesses })
  })
}

2. 修改Yelp.js

删除无用的SearchBar导入,补全参数接收逻辑,将term和location作为查询参数传递给后端接口,同时修复categories字段取值错误(Yelp返回的categories是数组,需要取第一个元素的title):

const Yelp = {
    searchYelp(term, location) {
    // 对参数编码避免特殊字符报错
    return fetch(`/api/hello?term=${encodeURIComponent(term)}&location=${encodeURIComponent(location)}`)
        .then((response) => {
            return response.json()
        }).then((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[0]?.title || '',
                        rating: business.rating,
                        reviewCount: business.review_count,
                    }
                })
            }
            return []
        })
    }
}

export default Yelp

3. 修改Server.js接口

原接口用路径参数只接收了term,且Yelp请求的url用了单引号导致模板字符串不生效,location变量未定义,修改为接收查询参数,修复模板字符串问题:

app.get('/api/hello', (req, res) => {
    const term = req.query.term
    const location = req.query.location
    // 可加非空判断,避免参数缺失报错
    if(!term || !location) return res.status(400).send('搜索词和位置不能为空')
    const config = {
        method: 'get',
        // 换成反引号让模板字符串生效
        url: `https://api.yelp.com/v3/businesses/search?term=${term}&location=${location}`,
        headers: {
            'Authorization': `Bearer ${apiKey}`
        }
    };

    axios(config)
        .then(function (response) {
            res.json(response.data)
        }) 
        .catch(function (error) {
            console.log(error);
            res.status(500).send('请求数据失败')
        });
});

内容的提问来源于stack exchange,提问作者Halp_am_stuck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:06:02