在 React 中获得太多的重新渲染

getting too many re-renders in react

提问人:imshoaibkhan 提问时间:11/17/2023 更新时间:11/17/2023 访问量:59

问:

我有一个名为 Search 的 React 组件,我在其中迭代数据项并为每个项呈现一个 SearchCard 组件。SearchCard 组件包含用于处理播放和暂停操作的逻辑。我注意到 SearchCard 组件中的控制台日志被多次触发,并且还发出了多个获取请求。

// SearchCard.jsx
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import PlayPause from "./PlayPause";
import { playPause, setActiveSong } from "../redux/features/playerSlice";
import { useEffect, useState } from "react";

const SearchCard = ({ song, i, isPlaying, activeSong, data }) => {
  const dispatch = useDispatch();

  console.log('heyyy!'); // This log statement is appearing multiple times

  const handlePauseClick = () => {
    dispatch(playPause(false));
  };

  const handlePlayClick = () => {
    dispatch(setActiveSong({ data, song, i }));
    dispatch(playPause(true));
  };

  // ... rest of the component

  return (
    // ... component JSX
  );
};

export default SearchCard;
// Search.jsx
import React from 'react';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { Error, Loader, SearchCard } from '../components';
import { useGetSongsBySearchQuery } from '../redux/services/shazam';

const Search = () => {
  const { searchTerm } = useParams();
  const { activeSong, isPlaying } = useSelector((state) => state.player);
  const { data, isFetching, error } = useGetSongsBySearchQuery(searchTerm);

  const songs = data?.tracks?.map((song) => song.data);

  if (isFetching) return <Loader title={`Searching ${searchTerm}...`} />;

  if (error) return <Error />;

  return (
    <div className="flex flex-col">
      <h2 className="font-bold text-3xl text-white text-left mt-4 mb-10">
        Showing results for <span className="font-black">{searchTerm}</span>
      </h2>

      <div className="flex flex-wrap sm:justify-start justify-center gap-8">
        {songs.map((song, i) => (
          <SearchCard
            key={song.id}
            song={song}
            isPlaying={isPlaying}
            activeSong={activeSong}
            data={data.tracks}
            i={i}
          />
        ))}
      </div>
    </div>
  );
};

export default Search;

预期行为:我希望 SearchCard 组件只记录一次,并且每个渲染的实例只获取一次数据。但是,它似乎多次记录和获取数据,导致意外行为。

JavaScript ReactJS 调试 渲染

评论


答:

-1赞 Kumar Shanu 11/17/2023 #1

您在 songs.map 中使用 SearchCard,因为对于每个迭代,都有一个控制台将记录假设您在 songs 数组中有五个元素,然后五个控制台将记录以避免这种情况 - 将您的网络调用移动到父级别

评论

0赞 Jaromanda X 11/17/2023
为什么这是报价?OP 的问题中没有 或showCardarray.map
0赞 Sachin Gautam 11/17/2023 #2
  1. 检查 useEffect 依赖项: 在 SearchCard.jsx 组件中,查看 useEffect 钩子(当前未显示在您提供的代码中),并确保已列出 useEffect 所依赖的所有依赖项。如果缺少任何依赖项,则可能导致意外行为。

2.优化渲染,避免副作用: 你可以使用 React.memo 来记住你的 SearchCard 组件,并在道具没有改变的情况下防止它重新渲染。但是,请记住,记忆是一种权衡,它可能并不适合所有方案。

  1. 在父组件中获取数据: 考虑将数据获取逻辑移动到父组件(在本例中为 Search.jsx),并将必要的数据作为 props 传递给 SearchCard 组件。这有助于集中数据提取并避免不必要的提取调用。

  2. 调试: 如果问题仍然存在,您可能需要使用浏览器开发人员工具来检查 React 组件树,并检查哪些组件正在渲染并导致额外的渲染。这可以帮助您确定意外行为的根本原因。