React点击Link跳转CountryDetail组件访问props属性报错如何解决?
错误原因
- 筛选函数逻辑错误
你写的onFilter函数里的筛选条件完全不对,目前的代码countries.filter((c) => c.name)只会筛选出所有存在name属性的国家,根本没有和传入的路由参数name做匹配,只要countries数组不为空永远返回第一个国家,匹配不到对应国家的时候也会返回错误数据。 - 空值没有做拦截
countries的初始值是空数组,路由第一次渲染的时候,onFilter会直接返回null,CountryDetail组件接收到的props就是null,这时候直接访问props.flag自然会触发「不能读取null的flag属性」的报错。你看到console.log能输出对象是因为浏览器控制台打印引用类型时是懒加载的,等你点开查看的时候countries已经完成了接口请求赋值,但组件同步渲染时props还是null,所以渲染失败。 - 路由结构错误
你把Form、AllCountries组件直接放在Router标签下,没有包在对应路由的Route里,不管跳转到哪个路由,这些组件都会一直显示,跳转到详情页的时候会出现列表和详情同时展示的问题。
修复方案
1. 修正筛选函数逻辑
把onFilter改成下面的写法,正确匹配国家名称:
function onFilter(name) { let country = countries.filter((c) => c.name === name); if (country.length > 0) { return country[0]; } else { return null; } }
2. 加空值保护
两种方案选一种即可:
- 路由渲染处加判断:
<Route exact path="/country/:name" render={({ match }) => { const country = onFilter(match.params.name) return country ? <CountryDetail country={country} /> : <div>加载中...</div> }} />
- CountryDetail组件内加可选链运算符:
function CountryDetail({ country }) { console.log(country); return ( <div className="details"> <div className="info"> <img src={country?.flag} className="flags" alt="国旗"></img> <ul>Name:{country?.name}</ul> <ul>Native Name: {country?.nativeName}</ul> {/* 其余属性都加?.前缀即可 */} </div> </div> ); }
3. 修正路由结构
如果要首页才显示表单和国家列表,把它们包在首页的Route里:
<Router> <Route path="/" component={Navbar} /> <Route exact path="/"> <Form onSearch={onSearch} setInput={setInput} setSearch={setSearch} input={input} setStatus={setStatus} /> <AllCountries countries={countries} search={search} filteredCountries={filteredCountries} /> </Route> <Route exact path="/country/:name" render={({ match }) => { const country = onFilter(match.params.name) return country ? <CountryDetail country={country} /> : <div>加载中...</div> }} /> </Router>
同类问题通用解决建议
- 所有要渲染的异步数据、可能为空的属性都要加空值判断,JSX里优先用可选链
?.做短路保护 - 数组筛选、查找逻辑写完要先做测试,确认返回值符合预期再传给子组件
- 引用类型的console.log不能作为实时值的判断依据,要用断点或者打印JSON.stringify后的结果确认取值时机是否正确
- 路由包裹的内容要注意层级,只有放在Route标签内的内容才会根据路由路径匹配渲染
内容的提问来源于stack exchange,提问作者miouri
相关产品推荐
相关产品推荐

