React中useState与useEffect配合API调用异常求助
React中IMDb API调用返回数据undefined的解决方法
问题背景
将训练营的简单HTML页面重构为React项目,使用useState管理状态,useEffect触发IMDb API调用,但异步流程异常,控制台显示返回数据为undefined,尝试过axios及async/await方式仍未解决。需求是通过useEffect调用API,等待数据返回并解析为JSON,再通过setData更新状态以展示数据。
当前代码
const [inputText, setInputText] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [data, setData] = useState(null); const handleChange = (event) => { setInputText(event.target.value); }; const handleSubmit = (event) => { event.preventDefault(); setSearchTerm(inputText) console.log(inputText) setInputText('') }; useEffect(() => { if (searchTerm) { console.log('starting fetch with -> ', `https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/${searchTerm}`) fetch(`https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/${searchTerm}`) .then(res => { res.json() console.log('json data') }) .then(json => { setData(json) console.log('setting data to this value', json) }) .then(console.log('current data value after setData runs -> ', data)) } }, [searchTerm])
控制台输出
inception App.js:36 starting fetch with -> https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/inception App.js:45 current data value after setData runs -> null App.js:40 json data App.js:44 setting data to this value undefined index.js:6 data value within body component currently is undefined installHook.js:1861 data value within body component currently is undefined index.js:6 data value within body component currently is undefined installHook.js:1861 data value within body component currently is undefined App.js:36 starting fetch with -> https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/inception App.js:45 current data value after setData runs -> undefined App.js:40 json data App.js:44 setting data to this value undefined
错误分析与修复方案
核心错误点
- 第一个
then未返回JSON数据:res.json()是异步操作,必须返回该结果才能传递到下一个then,否则后续then的json参数会是undefined。 - 状态更新后立即打印无效:
setData是异步操作,状态更新不会立即生效,后续then中打印的data仍是更新前的旧值。
修复后的代码(async/await版本)
const [inputText, setInputText] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [data, setData] = useState(null); const [error, setError] = useState(null); // 新增错误状态管理 const handleChange = (event) => { setInputText(event.target.value); }; const handleSubmit = (event) => { event.preventDefault(); setSearchTerm(inputText); setInputText(''); }; useEffect(() => { if (!searchTerm) return; const fetchMovieData = async () => { try { console.log('starting fetch with -> ', `https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/${searchTerm}`); const res = await fetch(`https://imdb-api.com/en/API/SearchTitle/k_ix11kdvq/${searchTerm}`); // 检查HTTP响应状态,处理请求失败情况 if (!res.ok) throw new Error(`请求失败,状态码:${res.status}`); const jsonData = await res.json(); setData(jsonData); console.log('成功获取数据:', jsonData); setError(null); // 清除之前的错误 } catch (err) { setError(err.message); console.error('请求出错:', err); } }; fetchMovieData(); }, [searchTerm]); // 组件渲染部分示例 return ( <div> <form onSubmit={handleSubmit}> <input value={inputText} onChange={handleChange} placeholder="输入电影名搜索..." /> <button type="submit">搜索</button> </form> {/* 错误提示 */} {error && <p style={{color: 'red'}}>错误:{error}</p>} {/* 数据展示 */} {data && data.results && ( <div className="search-results"> <h3>搜索结果</h3> {data.results.map(movie => ( <div key={movie.id} className="movie-item"> <h4>{movie.title}</h4> <p>{movie.description}</p> <img src={movie.image} alt={movie.title} width="100" /> </div> ))} </div> )} </div> );
关键修复说明
- 用
async/await简化异步流程,代码逻辑更直观。 - 添加HTTP响应状态检查,捕获请求失败的情况(如API密钥失效、网络异常)。
- 新增
error状态管理错误信息,避免用户看到空白页面。 - 状态更新后通过组件渲染展示数据,而非立即打印(
setData异步特性导致即时打印无意义)。
额外注意事项
- API密钥安全:不要在前端代码中直接暴露API密钥,建议通过后端代理转发请求,防止密钥被盗用。
- 防抖优化:频繁输入搜索词会触发多次API调用,可添加防抖函数(如
setTimeout延迟执行)减少请求次数。 - 空值判断:渲染数据前先检查
data和data.results是否存在,避免undefined报错。
内容的提问来源于stack exchange,提问作者Tneswick
相关产品推荐
相关产品推荐

