React Nothing was returned from render报错 卡片详情页加载失败
问题定位
控制台抛出的Uncaught Error: Info(...): Nothing was returned from render和你猜测的{...countries}props展开逻辑无关,根因在Info.jsx组件实现:
函数组件内写完状态定义、副作用逻辑后,直接编写了<Wrapper>开头的JSX结构,但没有写return关键字返回这段JSX,组件执行完成后默认返回undefined,React检测到渲染内容缺失就抛出了该错误,直接导致详情页无法正常渲染。
另外你的代码还存在一个隐性bug:解构出的push方法不存在,react-router-dom v6版本已经废弃了原v5版本的push跳转API,就算补上return,点击边境国家标签时也会触发报错。
修复方案
- 在Info组件中,给
<Wrapper>包裹的整段JSX外层加上return (和对应的闭合),确保组件正确返回渲染内容 - 从react-router-dom引入
useNavigate钩子替换不存在的push方法,实现边境国家的跳转逻辑 - (可选优化)原代码将同属详情信息的列表项拆分为多个独立
<ul>标签,不符合HTML语义,可合并为同个列表下的多个条目
修复后完整Info组件代码
import React from 'react'; import styled from 'styled-components'; import axios from 'axios'; import {useState, useEffect} from 'react'; import { useNavigate } from 'react-router-dom'; import { filterByCode } from '../config'; const Wrapper = styled.section` margin-top: 3rem; width: 100%; display: grid; grid-template-columns: 100%; gap: 2rem; @media (min-width: 767px) { grid-template-columns: minmax(100px, 400px) 1fr; align-items: center; gap: 5rem; } @media (min-width: 1024px) { grid-template-columns: minmax(400px, 600px) 1fr; } `; const InfoImage = styled.img` display: block; width: 100%; height: 100%; object-fit: contain; `; const InfoTitle = styled.h1` margin: 0; font-weight: var(--fw-normal); `; const ListGroup = styled.div` display: flex; flex-direction: column; gap: 2rem; @media (min-width: 1024px) { flex-direction: row; gap: 4rem; } `; const List = styled.ul` list-style: none; margin: 0; padding: 0; `; const ListItem = styled.li` line-height: 1.8; & > b { font-weight: var(--fw-bold); } `; const Meta = styled.div` margin-top: 3rem; display: flex; gap: 1.5rem; flex-direction: column; align-items: flex-start; & > b { font-weight: var(--fw-bold); } @media (min-width: 767px) { flex-direction: row; align-items: center; } `; const TagGroup = styled.div` display: flex; gap: 1rem; flex-wrap: wrap; `; const Tag = styled.span` padding: 0 1rem; background-color: var(--colors-ui-base); box-shadow: var(--shadow); line-height: 1.5; cursor: pointer; `; export const Info=(props)=>{ const { name, nativeName, flag, capital, population, region, subregion,topLevelDomain,currencies=[],languages=[],borders=[], }=props; const navigate = useNavigate(); const [neighbors, setNeighbors] = useState([]); useEffect(() => { if (borders.length) axios.get(filterByCode(borders)) .then(({ data }) => setNeighbors(data.map((c) => c.name))); }, [borders]); return ( <Wrapper> <div> <InfoImage src={flag} alt={name}/> <div> <InfoTitle>{name}</InfoTitle> </div> <ListGroup> <List> <ListItem> <b>Native Name:</b>{nativeName} </ListItem> <ListItem> <b>Population:</b>{population} </ListItem> <ListItem> <b>Region:</b>{region} </ListItem> <ListItem> <b>Subregion:</b>{subregion} </ListItem> <ListItem> <b>Capital:</b>{capital} </ListItem> </List> <List> <ListItem> <b>Top Level Domain:</b>{topLevelDomain.map((d)=>(<span key={d}>{d} </span>))} </ListItem> <ListItem> <b>Currencies:</b>{currencies.map((c)=>(<span key={c.code}>{c.name} </span>))} </ListItem> <ListItem> <b>Languages:</b>{languages.map((l)=>(<span key={l.name}>{l.name} </span>))} </ListItem> </List> </ListGroup> <Meta> <b>Border Countries</b> {!borders.length ? ( <span>There is no border countries</span> ) : ( <TagGroup> {neighbors.map((b) => ( <Tag key={b} onClick={() => navigate(`/country/${b}`)}> {b} </Tag> ))} </TagGroup> )} </Meta> </div> </Wrapper> ) };
补充说明
Details.jsx中{countries && <Info {...countries} />}的条件渲染、props展开逻辑均无问题,无需修改- 接口请求返回数据后会自动触发Info组件渲染,修复return缺失问题后点击首页卡片即可正常进入详情页
内容的提问来源于stack exchange,提问作者Michael Hamar
相关产品推荐
相关产品推荐

