React Context API使用问题:获取searchQuery返回undefined求助
Context API 获取值为undefined的问题排查与解决
错误原因
- 重复且无值的外层Provider:你在
index.js中添加了一个未传递value的SearchContext.Provider,这个最外层的Provider会让App及其所有子组件(包括NumberOfContestParticipated)优先使用它,而由于没有设置value,获取到的结果就是undefined。 - Provider作用范围不匹配:Search组件内部的
SearchContext.Provider仅包裹了自身的搜索UI,并没有将NumberOfContestParticipated包含在内,即便去掉外层空Provider,后者也无法拿到Search组件内的searchQuery。
解决方案
步骤1:移除多余的空Provider
修改index.js,删除无值的SearchContext.Provider,直接渲染App:
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; ReactDOM.render( <App />, document.getElementById('root') );
步骤2:提升状态到共同父组件,统一管理Context
将searchQuery状态和Context Provider提升到App组件(所有需要访问该状态的组件的共同父级),确保所有相关组件都在Provider范围内:
修改App.jsx:
import { useState } from 'react'; import Search from './components/Search'; import NumberOfContestParticipated from './components/NumberOfContestParticipated'; import SearchContext from './Context/SearchContext'; function App() { const [searchQuery, setSearchQuery] = useState(''); // 传递状态和更新函数,方便子组件使用 return ( <SearchContext.Provider value={{ searchQuery, setSearchQuery }}> <Search /> <NumberOfContestParticipated handle={searchQuery} /> </SearchContext.Provider> ); } export default App;
步骤3:修改Search组件,从Context获取更新函数
Search组件不再自行管理状态,而是通过Context获取setSearchQuery来更新搜索值:
import * as React from 'react'; import { useContext } from 'react'; import Paper from '@mui/material/Paper'; import AccountCircleIcon from '@mui/icons-material/AccountCircle'; import SearchIcon from '@mui/icons-material/Search'; import { Box, IconButton, InputBase } from '@mui/material'; import SearchContext from '../Context/SearchContext'; export default function Search() { const { setSearchQuery } = useContext(SearchContext); const handleSubmit = (event) => { event.preventDefault(); }; const handleInputChange = (event) => { setSearchQuery(event.target.value); }; return ( <Box display='flex' alignItems='center' justifyContent='center' paddingTop='20px'> <Paper component="form" sx={{ p: '2px 10px', display: 'flex', width: '50%' }} onSubmit={handleSubmit}> <IconButton type="button" sx={{ p: '10px' }} aria-label="search"> <AccountCircleIcon fontSize='large' /> </IconButton> <InputBase sx={{ ml: 1, flex: 1 }} placeholder="Search User" inputProps={{ 'aria-label': 'search user' }} onChange={handleInputChange} /> <IconButton type="submit" sx={{ p: '10px' }} aria-label="search"> <SearchIcon fontSize='large' /> </IconButton> </Paper> </Box> ); }
步骤4:更新NumberOfContestParticipated组件(可选)
如果需要直接从Context获取searchQuery,可以修改该组件的依赖为Context中的值:
import React, { useContext, useEffect, useState } from 'react'; import { ApiService } from '../../API/ApiService'; import SearchContext from '../../Context/SearchContext'; function NumberOfContestParticipated() { const [contestCount, setContestCount] = useState(null); const { searchQuery } = useContext(SearchContext); useEffect(() => { // 仅当searchQuery不为空时发起请求 if (!searchQuery) { setContestCount(null); return; } const fetchData = async () => { const ratingUrl = `https://codeforces.com/api/user.rating?handle=${searchQuery}`; const ratingData = await ApiService(ratingUrl); if (ratingData && ratingData.status === 'OK') { setContestCount(ratingData.result.length); } else { setContestCount(0); } }; fetchData(); }, [searchQuery]); return ( <div> {contestCount !== null ? ( <p>Number of contests participated by {searchQuery}: {contestCount}</p> ) : ( <p>Enter a username to load data...</p> )} </div> ); } export default NumberOfContestParticipated;
内容的提问来源于stack exchange,提问作者Akash Suklabaidya
相关产品推荐
相关产品推荐

