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

React项目宝可梦列表过滤后组件不重新渲染如何解决?

问题排查与修复方案

你代码里存在两处核心问题导致列表不更新:

1. App组件中useMemo使用错误

你当前的useMemo写法不符合规范:

  • 把_data空数组声明在useMemo外部,还将_data放入依赖数组,会导致缓存逻辑完全失效
  • 用map遍历并往外部数组推送数据的写法冗余,也容易引发引用异常
    修正后的App组件对应代码:
import React from "react";

import { types, pokemons } from "./data";

import Avatar from "./components/Avatar";
import List from "./components/List";

import "./styles.css";

const App = () => {
  const [favorite, setFavorite] = React.useState("rock");

  // 直接用useMemo返回过滤去重后的数组,依赖项只放pokemons和favorite
  const filteredPokemons = React.useMemo(() => {
    // 先过滤符合类型的宝可梦
    const matched = pokemons.filter(pokemon => 
      pokemon.type.includes(favorite.toLowerCase())
    );
    // 去重逻辑合并到memo里
    const nameSet = new Set();
    return matched.filter(pokemon => {
      if (!nameSet.has(pokemon.name)) {
        nameSet.add(pokemon.name);
        return true;
      }
      return false;
    })
  }, [pokemons, favorite]);

  return (
    <div className="App">
      <Avatar data={types} setFavorite={setFavorite} />
      <List data={filteredPokemons} />
    </div>
  );
};

export default App;

2. List组件内部state没有同步父组件传参更新

你在List组件中把父组件传的data作为pokemonsState的初始值,但useState的初始值仅在组件第一次挂载时生效,父组件传入的data更新时,内部state不会自动同步。
两种修复方案二选一即可:

方案一:添加监听逻辑同步props

给List组件加useEffect监听data变化,自动更新内部state:

import { useState, useEffect } from 'react';
// 其他导入省略

const List = ({ data }) => {
  const [pokemonsState, setPokemonsState] = useState(data);
  const [isAscSort, setIsAscSort] = useState(false);

  // 新增:监听data和排序规则变化,自动更新列表
  useEffect(() => {
    setPokemonsState(stableSort(data, getComparator(isAscSort ? "asc" : "desc", "name")));
  }, [data, isAscSort])

  const sortPokemon = () => {
    setIsAscSort(!isAscSort);
  };

  // 其余渲染逻辑保持不变
};

方案二:删除内部state,直接使用props.data

如果不需要额外缓存逻辑,直接用props的data进行渲染和排序即可,完全避免不同步问题:

// 其他导入省略

const List = ({ data }) => {
  const [isAscSort, setIsAscSort] = useState(false);

  // 每次渲染直接根据当前排序规则处理data
  const sortedPokemons = stableSort(data, getComparator(isAscSort ? "asc" : "desc", "name"));

  const sortPokemon = () => {
    setIsAscSort(!isAscSort);
  };

  return (
    <TableContainer>
      <Table sx={{ minWidth: 650 }}>
        <TableHead>
          <TableRow>
            <TableCell>Pokémon</TableCell>

            <TableCell name onClick={() => sortPokemon()} align="right">
              Name
              {!isAscSort ? <ArrowUpward /> : <ArrowDownward />}
            </TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {/* 直接用sortedPokemons渲染 */}
          {sortedPokemons.map((pokemon, idx) => (
            <TableRow
              key={idx}
              sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
            >
              <TableCell component="th" scope="row" thumbnailImage>
                <div className="thumb">
                  <img src={pokemon.thumbnailImage} alt="" />
                </div>
              </TableCell>
              <TableCell align="left" component="th" scope="row" description>
                {pokemon.name}
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

修改以上两处问题后,点击类型切换时列表就会正常更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:18:01