React中如何将多个对象类型state合并为单个数组并访问使用?
问题点梳理
- 两个异步请求返回时序不确定,没有监听两个数据的加载状态就直接合并,会出现缺数据的情况
definition初始类型为字符串,和后续要存储的对象数组类型不匹配- 缺少请求错误、返回数据为空的边界处理,接口异常时会直接抛出JS报错
- 第二个axios配置存在笔误,
dataResponse应为标准属性responseType
方案1:保留原有双state逻辑(推荐需要单独使用两个对象的场景)
代码修正
import { useState, useEffect } from 'react'; import axios from 'axios'; // 调整state定义,新增加载状态标识,definition改为数组类型 const [ourWord, setOurWord] = useState({key: 0, word: '', definition: '', isLoaded: false}); const [homophone, setHomophone] = useState({key: 1, word: '', definition: '', isLoaded: false}); const [definition, setDefinition] = useState([]); // 第一个请求:获取初始词信息 useEffect( () => { axios({ url: `https://api.dictionaryapi.dev/api/v2/entries/en/${startingWord}`, }) .then(res => { if (res.data?.[0]) { setOurWord({ key: 0, word: res.data[0].word, definition: res.data[0].meanings?.[0]?.definitions?.[0]?.definition || '暂无释义', isLoaded: true }); } else { setOurWord(prev => ({...prev, isLoaded: true})) } }) .catch(err => { console.error('初始词查询失败', err) setOurWord(prev => ({...prev, isLoaded: true})) }) }, [startingWord]) // 补充startingWord依赖,初始词变化时自动重新请求 // 第二个请求:获取同音字信息 useEffect( () => { axios({ url: 'https://api.datamuse.com/words', method: 'GET', responseType: 'json', params: { md: "d", rel_hom: startingWord, } }).then(res => { const wordWithDefinition = res.data.filter(item => item.defs); if (wordWithDefinition.length) { setHomophone({ key: 1, word: wordWithDefinition[0].word, definition: wordWithDefinition[0].defs[0] || '暂无释义', isLoaded: true }) } else { setHomophone(prev => ({...prev, isLoaded: true})) } }) .catch(err => { console.error('同音字查询失败', err) setHomophone(prev => ({...prev, isLoaded: true})) }) }, [startingWord]); // 监听两个数据加载状态,完成后合并为数组 useEffect(() => { if (ourWord.isLoaded && homophone.isLoaded) { // 可根据需求过滤无有效内容的空对象 const mergedList = [ourWord, homophone].filter(item => item.word) setDefinition(mergedList) } }, [ourWord, homophone])
JSX使用示例
- 按key获取指定对象:
const target = definition.find(item => item.key === 0)即可拿到初始词的对象 - 列表渲染:
{definition.map(item => ( <div key={item.key}> <p>*词汇:{item.word}</p> <p>释义:{item.definition}</p> </div> ))}
方案2:使用Promise.all简化逻辑(推荐不需要单独维护两个对象的场景)
无需维护三个state,直接并发请求、统一处理结果,代码更简洁:
import { useState, useEffect } from 'react'; import axios from 'axios'; const [definition, setDefinition] = useState([]) useEffect(() => { // 并发发起两个请求,全部返回后统一处理 Promise.all([ axios({url: `https://api.dictionaryapi.dev/api/v2/entries/en/${startingWord}`}), axios({ url: 'https://api.datamuse.com/words', method: 'GET', responseType: 'json', params: {md: "d", rel_hom: startingWord} }) ]).then(([wordRes, homophoneRes]) => { const mergedList = [] // 处理初始词结果 if (wordRes.data?.[0]) { mergedList.push({ key: 0, word: wordRes.data[0].word, definition: wordRes.data[0].meanings?.[0]?.definitions?.[0]?.definition || '暂无释义' }) } // 处理同音字结果 const validHomophone = homophoneRes.data.filter(item => item.defs) if (validHomophone.length) { mergedList.push({ key: 1, word: validHomophone[0].word, definition: validHomophone[0].defs[0] || '暂无释义' }) } setDefinition(mergedList) }).catch(err => { console.error('请求失败', err) }) }, [startingWord])
内容的提问来源于stack exchange,提问作者cjh4549
相关产品推荐
相关产品推荐

