React自定义Helper组件fetch后setState赋值状态为undefined如何解决
问题原因及解决方案
你遇到的问题由4个核心错误导致,逐一说明如下:
1. state取值语法错误
React类组件的所有状态都存储在this.state对象下,你写的this.movieAnswer是直接访问实例上不存在的属性,永远返回undefined,正确的取值方式是this.state.movieAnswer。
2. setState是异步更新逻辑
React的setState是批量异步执行的,调用后不会立刻修改this.state的值,你在setState语句后紧跟打印,拿到的还是更新前的旧值。如果需要拿到更新后的值,要使用setState的第二个参数回调:
setMovieResponse = (response) => { console.log("get call ? ",response) // 第二个参数是更新完成后的回调 this.setState({ movieAnswer: JSON.stringify(response)}, () => { console.log("get SET ? ",this.state.movieAnswer) // 这里才能拿到最新值 }); }
3. fetch是异步操作,同步返回无法拿到结果
fetch请求是异步执行的,调用fetchMovieFunction时,请求还没完成就已经执行到return语句,此时返回的还是state的初始值,自然拿不到接口返回的数据。
4. React组件不能手动new实例调用
你在Game.js中写const Help = new Helper();是完全不符合React规范的用法,React组件必须通过JSX渲染(比如<Helper />),由React内部管理实例生命周期,手动new出来的实例状态更新不会触发任何视图响应,也无法正常使用React的相关特性。
正确改造方案
你这个Helper只是用来封装接口请求,完全不需要做成React组件,直接抽离为普通异步工具函数即可:
第一步:改写helper.js为工具函数文件
const API_KEY = process.env.REACT_APP_API_KEY; const PERSON_KEY = process.env.REACT_APP_PERSON; const MOVIE_KEY = process.env.REACT_APP_MOVIE; const myInit = {method: "GET", mode: "cors"} // 电影请求函数,返回Promise export const fetchMovieFunction = async (randomMovie) => { const res = await fetch(`${MOVIE_KEY}${randomMovie}?api_key=${API_KEY}`, myInit) const data = await res.json() return JSON.stringify(data) } // 演员请求函数,返回Promise export const fetchPersonFunction = async (randomActor) => { const res = await fetch(`${PERSON_KEY}${randomActor}?api_key=${API_KEY}`, myInit) const data = await res.json() return data.total }
第二步:在Game组件中异步调用并存储状态
以函数组件为例:
import { useEffect, useState } from 'react' import { fetchMovieFunction } from './helper' const Game = () => { const [movieAnswer, setMovieAnswer] = useState("") const getMovieData = async (randomMovie) => { const res = await fetchMovieFunction(randomMovie) setMovieAnswer(res) console.log("MOVIE res = ", res) } // 示例:组件挂载后调用请求,可根据你的逻辑调整触发时机 useEffect(() => { const randomMovie = '替换为你的实际参数' getMovieData(randomMovie) }, []) return <div>{/* 你的页面渲染逻辑 */}</div> } export default Game
内容的提问来源于stack exchange,提问作者Quentin Riols
相关产品推荐
相关产品推荐

