You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:35:46