React动态路由结合WordPress API:详情页无法渲染文章数据求助
问题诊断与修复方案
嘿,我帮你排查了代码里的问题,核心问题集中在这几个点:
1. 路由定义位置错误
你把<Route>放在了map循环内部,每渲染一篇文章预览就生成一个路由规则。这不仅完全没必要,还会导致路由匹配逻辑混乱——React Router会匹配所有符合条件的路由,重复渲染Article组件。
2. 传递给Article的数据源完全错误
你传给Article的data={articles},但articles是map返回的JSX元素数组(也就是你渲染出来的文章预览DOM结构),不是原始的博客数据数组!所以data.find(a => a.slug == match.params.articleSlug)根本找不到任何匹配的对象,因为数组里的元素都是<div>之类的React元素,不是文章对象。
3. 加载/错误状态的判断逻辑位置不对
你在map循环里判断加载失败和加载中,这会导致:
- 当还在加载时,
newsData是空数组,map不会执行,加载中的提示根本不会显示 - 如果加载失败,
map会给每个(不存在的)文章都渲染一个错误提示,逻辑完全混乱
修复后的代码
Articles.js(修改后的版本)
import React, { Component } from 'react'; import { Link, Route } from 'react-router-dom'; import Article from './Article'; const newsURL = "http://myprivateblogapi.com/wp-json/wp/v2/posts?_embed"; export default class Articles extends Component { constructor(props) { super(props); this.state = { newsData: [], requestFailed: false, isLoading: true // 新增明确的加载状态标识 } } componentDidMount() { fetch(newsURL) .then(response => { if(!response.ok) { throw Error("Network request failed."); } return response }) .then(d => d.json()) .then(d => { this.setState({ newsData: d, isLoading: false // 加载完成,更新状态 }) }, () => { this.setState({ requestFailed: true, isLoading: false // 加载失败,更新状态 }) }) } render() { // 先统一处理加载和错误状态,逻辑更清晰 if(this.state.isLoading) return <p>加载中...</p>; if(this.state.requestFailed) return <p>加载失败!</p>; // 单独生成文章预览列表 const articlePreviews = this.state.newsData.map((article, index) => ( <div key={index} className="article-container"> <div className="article-preview"> <span className="article-date">{article.date}</span> <h5>{article.title.rendered}</h5> <div dangerouslySetInnerHTML={{ __html: article.excerpt.rendered }} /> <Link to={`/news/${article.slug}`}>阅读更多...</Link> </div> </div> )); return ( <div> <h3>博客所有文章</h3> {articlePreviews} {/* 把Route移到循环外面,只定义一次,传递正确的原始数据源 */} <Route path={`/news/:articleSlug`} render={ (props) => <Article data={this.state.newsData} {...props} />} /> </div> ) } }
Article.js(优化版)
import React from 'react'; const Article = ({match, data}) => { const article = data.find(a => a.slug === match.params.articleSlug); if (!article) { return <h2>抱歉,该文章不存在。</h2>; } return ( <div> <h3>{article.title.rendered}</h3> {/* 注意:文章内容是HTML字符串,必须用dangerouslySetInnerHTML渲染 */} <div dangerouslySetInnerHTML={{ __html: article.content.rendered }} /> <hr /> </div> ) } export default Article;
另外提个小细节:你之前在Article里用{ console.log(...) },这会在渲染时把console的返回值(undefined)也插入到DOM中,虽然看不到,但最好去掉,或者把console.log放在组件的逻辑代码里,不要写在JSX结构中。
内容的提问来源于stack exchange,提问作者bluebrooklynbrim
相关产品推荐
相关产品推荐

