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

传递Props时State未更新:React轮播组件数据展示异常

React轮播组件数据展示异常问题修复

问题描述

在React应用中实现了Carousel轮播和Button可复用组件,点击按钮应获取对应API数据(posts/users/comments)并在轮播中展示,但实际出现点击Users按钮显示Posts数据、点击Comments按钮显示Users数据的异常情况。

相关代码

Testimonials组件

import { useState, useEffect } from "react";

export default function Testimonials() {
  const [testimonail, setTestimonial] = useState();
  const [items, setItems] = useState([]);

  useEffect(() => {
    fetch(
      `https://jsonplaceholder.typicode.com/${testimonail}?_start=0&_limit=5`
    )
      .then((res) => res.json())
      .then((json) => setItems(json));
  }, [testimonail]);
  const handleClick = (post) => {
    console.log("targetId", post);
    setTestimonial(post);
  };
  return (
    <div>
      <Carousel items={items} />
      <Button
        id="posts"
        btnName="Post"
        classes="btn-primary mr-2"
        onClick={() => handleClick("posts")}
      />
      <Button
        id="users"
        btnName="User"
        classes="btn-info mr-2"
        onClick={() => handleClick("users")}
      />
      <Button
        id="comments"
        btnName="Comment"
        classes="btn-dark mr-2"
        onClick={() => handleClick("comments")}
      />
    </div>
  );
}

Carousel组件

export default function Carousel({ items }) {
  return (
    <div>
      <div class="container-fluid">
        <OwlCarousel items={1} className="owl-theme" loop nav margin={8}>
          {items.length > 0
            ? items.map((item, id) => {
                return (
                  <div className="main-conatainer" key={item.id}>
                    <div className="testimonail-block">
                      <div className="left-images">
                        <img
                          className="img"
                          alt="testimonial-images"
                          src="assests/images/1.png"
                        />
                      </div>
                      <div className="posts">
                        <p>{item.body}</p>
                        <div className="testimonial-title">{item.title}</div>
                      </div>
                    </div>
                  </div>
                );
              })
            : ""}
        </OwlCarousel>
      </div>
    </div>
  );
}

问题根源

  1. 数据结构不匹配:Carousel硬编码渲染item.body和item.title,但Users/Comments数据的字段与Posts不一致:
    • Users数据包含name/email等字段,无title/body
    • Comments数据包含body但无title
      字段缺失导致切换数据时显示异常,被误认为是旧数据残留。
  2. 初始状态未处理:testimonail初始值为undefined,首次渲染会发起无效API请求,可能引发潜在错误。
  3. 轮播组件未响应数据更新:OwlCarousel未在数据源变化时重新初始化,导致旧数据残留。

修复方案

1. 动态适配不同数据类型的渲染内容

修改Testimonials组件传递数据类型标识,Carousel根据类型渲染对应字段:

优化后的Testimonials组件

import { useState, useEffect } from "react";

export default function Testimonials() {
  // 初始化默认数据类型为posts,避免无效请求
  const [testimonialType, setTestimonialType] = useState("posts");
  const [items, setItems] = useState([]);

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/${testimonialType}?_start=0&_limit=5`)
      .then((res) => res.json())
      .then((json) => setItems(json))
      .catch(err => console.error('数据获取失败:', err)); // 添加错误捕获
  }, [testimonialType]);

  const handleClick = (type) => {
    setTestimonialType(type);
  };

  return (
    <div>
      {/* 传递当前数据类型给Carousel */}
      <Carousel items={items} dataType={testimonialType} />
      <Button
        id="posts"
        btnName="Post"
        classes="btn-primary mr-2"
        onClick={() => handleClick("posts")}
      />
      <Button
        id="users"
        btnName="User"
        classes="btn-info mr-2"
        onClick={() => handleClick("users")}
      />
      <Button
        id="comments"
        btnName="Comment"
        classes="btn-dark mr-2"
        onClick={() => handleClick("comments")}
      />
    </div>
  );
}

优化后的Carousel组件

export default function Carousel({ items, dataType }) {
  // 根据数据类型渲染对应内容
  const renderContent = (item) => {
    switch(dataType) {
      case "posts":
        return (
          <div className="posts">
            <p>{item.body}</p>
            <div className="testimonial-title">{item.title}</div>
          </div>
        );
      case "users":
        return (
          <div className="users">
            <p>{item.email}</p>
            <div className="testimonial-title">{item.name}</div>
          </div>
        );
      case "comments":
        return (
          <div className="comments">
            <p>{item.body}</p>
            <div className="testimonial-title">{item.name}</div>
          </div>
        );
      default:
        return null;
    }
  };

  return (
    <div>
      {/* React中需用className替代class */}
      <div className="container-fluid">
        {/* 添加key确保数据类型切换时重新初始化轮播 */}
        <OwlCarousel 
          items={1} 
          className="owl-theme" 
          loop 
          nav 
          margin={8}
          key={dataType}
        >
          {items.length > 0
            ? items.map((item) => (
                <div className="main-conatainer" key={item.id}>
                  <div className="testimonail-block">
                    <div className="left-images">
                      <img
                        className="img"
                        alt="testimonial-images"
                        src="assests/images/1.png"
                      />
                    </div>
                    {renderContent(item)}
                  </div>
                </div>
              ))
            : <div>暂无数据</div>} {/* 添加空状态提示 */}
        </OwlCarousel>
      </div>
    </div>
  );
}

2. 其他优化点

  • 修正变量名拼写不一致问题,用testimonialType替代原拼写混乱的testimonail
  • 给useState设置初始值,避免首次无效API请求
  • 添加fetch错误处理,便于排查请求问题
  • 替换React中不支持的class为className
  • 添加空状态提示,提升用户体验
  • 给OwlCarousel添加key属性,确保数据切换时组件重新渲染,避免旧数据残留

内容的提问来源于stack exchange,提问作者Partha Kundu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:35:53