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

React实现点击过滤数组并默认显示全部数据的问题

问题分析与解决方案

问题根源

  1. 当前data变量始终基于原始的toDoData生成,点击按钮更新filterCompleted状态后,data不会重新计算,页面内容自然不会变化。
  2. 若改成filterCompleted.map,初始时filterCompleted是空数组,且API请求完成后仅更新了toDoData,未同步更新filterCompleted,导致初始页面无内容。

解决方案一:同步过滤状态的初始数据

修改App.jsx,让filterCompleted在API请求完成后同步获取全部数据,并且始终基于filterCompleted生成页面内容:

import React from "react";
import Data from "../components/Data";
import "./App.css";

export default function App() {
  const [toDoData, setToDoData] = React.useState([]);
  const [filterCompleted, setFilterCompleted] = React.useState([]);
  
  React.useEffect(function () {
    fetch(`https://jsonplaceholder.typicode.com/todos`)
      .then((res) => res.json())
      .then((data) => {
        setToDoData(data);
        // 初始加载时把全部数据赋值给filterCompleted
        setFilterCompleted(data);
      });
  }, []);

  // 基于filterCompleted生成展示内容
  const data = filterCompleted.map((item) => { 
    return (
      <Data
        key={item.id}
        userId={item.userId}
        title={item.title}
        completed={item.completed ? "true" : "false"}
      />
    );
  });

  function handleCompleted() {
    const completedArray = toDoData.filter((data) => data.completed);
    setFilterCompleted(completedArray);
  }

  function handleNotCompleted() {
    const notCompletedArray = toDoData.filter((data) => !data.completed);
    setFilterCompleted(notCompletedArray);
  }

  function handleAll() {
    setFilterCompleted(toDoData);
  }

  return (
    <div>
      <div className="btn">
        <button onClick={handleCompleted}>Completed</button>
        <button onClick={handleNotCompleted}>Not Completed</button>
        <button onClick={handleAll}>All</button>
      </div>
      <div className="data">{data}</div>
    </div>
  );
}

解决方案二:使用过滤条件状态(更简洁推荐)

去掉filterCompleted状态,改用一个记录当前过滤类型的状态,根据类型实时过滤原始数据:

import React from "react";
import Data from "../components/Data";
import "./App.css";

export default function App() {
  const [toDoData, setToDoData] = React.useState([]);
  // 记录当前过滤类型:'all' | 'completed' | 'notCompleted'
  const [currentFilter, setCurrentFilter] = React.useState('all');
  
  React.useEffect(function () {
    fetch(`https://jsonplaceholder.typicode.com/todos`)
      .then((res) => res.json())
      .then((data) => {
        setToDoData(data);
      });
  }, []);

  // 根据当前过滤条件实时过滤数据
  const filteredData = toDoData.filter(item => {
    if (currentFilter === 'completed') return item.completed;
    if (currentFilter === 'notCompleted') return !item.completed;
    return true; // all的情况返回所有数据
  });

  const data = filteredData.map((item) => { 
    return (
      <Data
        key={item.id}
        userId={item.userId}
        title={item.title}
        completed={item.completed ? "true" : "false"}
      />
    );
  });

  return (
    <div>
      <div className="btn">
        <button onClick={() => setCurrentFilter('completed')}>Completed</button>
        <button onClick={() => setCurrentFilter('notCompleted')}>Not Completed</button>
        <button onClick={() => setCurrentFilter('all')}>All</button>
      </div>
      <div className="data">{data}</div>
    </div>
  );
}

关键修改点

  • 方案一中,在API请求完成后同步更新filterCompleted,确保初始显示全部数据;同时让页面内容基于filterCompleted生成,状态变化时自动更新页面。
  • 方案二中,通过currentFilter状态控制过滤逻辑,无需维护两份数据,代码更简洁,也避免了状态不同步的问题。

内容的提问来源于stack exchange,提问作者Nguyen Thanh Hien

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:43:30