React App组件中state的repos为什么无法从JSON获取数据?
问题产生的核心原因如下:
- 异步逻辑执行顺序错误
fetch请求是异步操作,你在调用fetchLanguageRepos之后立即打印this.state.repos时,请求还未返回结果,setState也还没执行,自然拿到的是初始值null。同时你把console.log(this.state.repos)直接写在了then的第二个参数位置,这个位置是请求失败的回调,会同步执行而非等待请求成功后执行,属于语法写错了。
另外setState本身也是异步更新的,就算你在请求成功的回调里刚执行完setState就打印state,也拿不到最新值,需要放在setState的第二个回调参数里才能拿到更新后的值。 - 请求路径错误
你在fetchLanguageRepos里写的请求路径是相对路径app/languagesdata.json,这个路径是相对于当前页面的URL地址的。之前的组件如果是在/app路由下运行,相对路径能正确命中资源,迁移到根组件App之后,页面URL如果是根路径/,请求地址就会变成/app/languagesdata.json,如果你的json文件没有放在对应部署路径下就会请求失败。建议改成绝对路径/app/languagesdata.json(开头加斜杠),不管当前路由是什么都会从站点根目录查找资源。 - 生命周期使用错误
componentWillMount是React已经废弃的生命周期,不建议使用。你说componentDidMount无法触发请求大概率是之前写法有误,根组件的componentDidMount一定会在挂载后正常执行,换回这个生命周期即可。 - 其它语法问题
fetchLanguageRepos定义时没有接收参数,你调用时传入的selectedLanguage根本没被接收处理,如果你需要按语言筛选数据要补全参数逻辑。- catch回调里没有接收error参数,直接使用
error变量会报未定义错误,要改成.catch((error) => {。 - render阶段没有处理repos为null的加载状态,子组件拿到的初始值都是null,建议加个加载提示的判断逻辑。
修正后的核心代码参考:
1. App组件生命周期和updateLanguage方法修正
// 换回标准生命周期 componentDidMount () { this.updateLanguage(this.state.selectedLanguage) } updateLanguage (selectedLanguage) { this.setState({ selectedLanguage, error: null, repos: null // 切换语言时重置数据 }) fetchLanguageRepos(selectedLanguage) .then((repos) => { this.setState({ repos, error: null, }, () => { // setState回调里才能拿到最新的repos console.log('更新后的repos:', this.state.repos) }) }) .catch((error) => { console.warn('Error fetching repos: ', error) this.setState({ error: 'There was an error fetching the repositories.' }) }) }
2. api.js修正
// 补全参数接收,路径改成绝对路径 export function fetchLanguageRepos (lang) { const endpoint = '/app/languagesdata.json' // 如果需要按语言筛选可以在这里加逻辑 return fetch(endpoint) .then((res) => { if (!res.ok) throw new Error('请求失败') return res.json() }) .then((data) => { if (!data.languages) { throw new Error(data.message || '数据格式错误') } return data.languages }) }
内容的提问来源于stack exchange,提问作者Julen Clarke
相关产品推荐
相关产品推荐

