React.js提交搜索后更新Bing Web API搜索结果(SERP格式)求助
问题描述
使用Bing Web Search API时,在自定义搜索栏输入查询能获取数据,但提交后无法将数据展示在搜索结果中,需要访问返回数据里webPages下的value元素。
相关代码
useSearch.js
import { useState, useEffect } from 'react'; import axios from 'axios'; const BASE_URL = 'https://api.bing.microsoft.com/v7.0/search'; const API_KEY = '0760f20a58f340a4ba3ce10857c43142' const useSearch = ( {searchTerm} ) => { const [data, setData] = useState(''); useEffect(() => { const fetchData = async () => { if (!searchTerm) return; try { const response = await axios.get(`${BASE_URL}`, { headers: { 'Ocp-Apim-Subscription-Key': API_KEY, }, params: { 'q': `${searchTerm}`, 'count': 10, 'mkt': 'en-us', }, }); setData(response.data.webPages.value); // shows data from search bar console.log(response.data); } catch (error) { console.error('Error fetching data:', error); } }; fetchData(); }, [searchTerm]); return data; }; export default useSearch;
SearchResults.js
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import TileItems from './TileItems'; import useSearch from './UseSearch'; const SearchResults = () => { const [theme, setTheme] = useState('light'); const { data } = useSearch({ searchTerm: searchData }); return ( <div className=''> <main className={`main-container ${theme}`}> <section className="eighty" id="item-tiles"> <h1>Search Results</h1> {data ? ( <ul> {data.map((i) => ( <TileItems key={i.id} image={i.thumbnailUrl} title={i.name} description={i.snippet} website={i.url} /> ))} </ul> ) : ( <p>Loading...</p> )} </section> <section id="item-tiles-right" className="twenty"> <h2 id='col-2-header'>News</h2> {video ? ( <ul> {/* this section is still under development */} {video.map((v) => ( <iframe id='ytplayer' src={v.contentUrl} frameborder='0' allow='autoplay; encrypted-media' width='100%' height='360' title='video' /> ))} </ul> ) : ( <p>Loading...</p> )} </section> </main> </div> ); };
Nav.js
import React, { useState } from 'react'; import './NavBar.css'; import logo_light from '../../assets/spigot-logo.png'; import logo_dark from '../../assets/logo_light2.png'; import search_icon_light from '../../assets/search-w.png'; import search_icon_dark from '../../assets/search-b.png'; import toggle_light from '../../assets/night.png'; import toggle_dark from '../../assets/day.png'; import useSearch from '../UseSearch'; function NavBar({theme, setTheme, setSearchTerm}) { const [searchQuery, setSearchQuery] = useState(''); const { data } = useSearch({ searchTerm: searchQuery}); // console.log(setSearchQuery); /* ternary clause to change theme between light and dark mode */ const toggle_mode = () => { theme == 'light' ? setTheme('dark') : setTheme('light'); } return ( <div className='navbar' > <img src={theme == 'light' ? logo_light : logo_dark} alt='' className='logo' /> <ul className='nav-list'> <li>SEARCH</li> </ul> <div className='search-box'> <form> <input className='search-bar' type='text' placeholder='Search' onChange={(e) => setSearchQuery(e.target.value)}></input> </form> <img className='search-icon' src={theme == 'light' ? search_icon_light : search_icon_dark} alt='' /> </div> <img onClick={() => {toggle_mode()}} src={theme == 'light' ? toggle_light : toggle_dark} alt='' className='toggle-icon'></img> </div> ) } export default NavBar
解决方案
核心问题梳理
- 搜索状态未全局同步:
NavBar的searchQuery和SearchResults的searchData无关联,导致结果组件拿不到用户输入的关键词。 - Hook返回值使用错误:
useSearch直接返回data,但组件里用了解构语法const { data } = useSearch(...),引发解构错误。 - 初始状态类型不匹配:
useSearch中data初始值是空字符串,后续要存储数组,类型不匹配会导致map调用失败。 - 未定义变量直接使用:
SearchResults里的searchData和video未声明,直接使用会触发报错。
分步修复
1. 全局管理搜索状态
在父组件(如App.js)中统一维护搜索关键词,通过props传递给子组件:
// App.js示例 import React, { useState } from 'react'; import NavBar from './components/Nav'; import SearchResults from './components/SearchResults'; function App() { const [theme, setTheme] = useState('light'); const [searchTerm, setSearchTerm] = useState(''); return ( <div className={`App ${theme}`}> <NavBar theme={theme} setTheme={setTheme} setSearchTerm={setSearchTerm} /> <SearchResults searchTerm={searchTerm} /> </div> ); } export default App;
2. 修复NavBar组件,同步搜索关键词
更新NavBar,在表单提交时将输入的查询同步到父组件,并移除不必要的useSearch调用:
// Nav.js修改部分 <form onSubmit={(e) => { e.preventDefault(); setSearchTerm(searchQuery); }}> <input className='search-bar' type='text' placeholder='Search' onChange={(e) => setSearchQuery(e.target.value)} value={searchQuery} /> </form>
3. 调整useSearch Hook的初始状态与容错逻辑
// useSearch.js修改 const useSearch = ( {searchTerm} ) => { const [data, setData] = useState([]); // 初始值设为空数组,匹配后续数据类型 useEffect(() => { const fetchData = async () => { if (!searchTerm) { setData([]); return; } try { const response = await axios.get(BASE_URL, { headers: { 'Ocp-Apim-Subscription-Key': API_KEY, }, params: { q: searchTerm, count: 10, mkt: 'en-us', }, }); // 增加容错,避免webPages不存在时抛出错误 setData(response.data.webPages?.value || []); } catch (error) { console.error('Error fetching data:', error); setData([]); } }; fetchData(); }, [searchTerm]); return data; // 直接返回数组,无需包装成对象 };
4. 修复SearchResults组件的变量问题
// SearchResults.js修改 import React from 'react'; import TileItems from './TileItems'; import useSearch from './UseSearch'; const SearchResults = ({ searchTerm }) => { const data = useSearch({ searchTerm }); // 直接接收返回的数组 return ( <div className=''> <main className={`main-container`}> <section className="eighty" id="item-tiles"> <h1>Search Results</h1> {data.length > 0 ? ( <ul> {data.map((item) => ( <TileItems key={item.id} image={item.thumbnailUrl} title={item.name} description={item.snippet} website={item.url} /> ))} </ul> ) : ( searchTerm ? <p>No results found</p> : <p>Enter a search term</p> )} </section> <section id="item-tiles-right" className="twenty"> <h2 id='col-2-header'>News</h2> <p>Under development</p> </section> </main> </div> ); };
验证要点
- 检查浏览器控制台是否有未定义变量、解构错误等提示。
- 确认API请求成功后,
response.data.webPages.value能正确获取到结果数组。 - 验证搜索关键词在父组件、
NavBar、SearchResults之间的传递是否顺畅。
内容的提问来源于stack exchange,提问作者jesse morris
相关产品推荐
相关产品推荐

