Home > front end >  Redux toolkit query trying... I don't know why there are too many re-renders?
Redux toolkit query trying... I don't know why there are too many re-renders?

Time:11-14

There is a Playlist component, user can choose different tag show different data. And some tag has banner and some not. The data are all fetched by reduxt-toolkit-query.

  • hightqualityTags.tags: a tag array which has banner

It seems setBannerVisibility() be used in wrong place...

Playlist.jsx

import { useState } from "react";

import HighqualityBanner from "../components/Playlist/HighqualityBanner";
import Catlist from "../components/Playlist/Catlist";
import PlaylistItem from "../components/Playlist/PlaylistItem";

import { useGetPlaylistHighqualityTagsQuery } from "../redux/services/neteaseCloudMusic";

const Playlist = () => {
  // tag logic
  const initialTag = "全部歌单";
  const [currentTag, setCurrentTag] = useState(initialTag);

  const onSelectTag = (tag) => {
    setCurrentTag(tag);
  };

  //set banner visibility
  const [bannerVisibility, setBannerVisibility] = useState(true);

  const { data: hightqualityTags } = useGetPlaylistHighqualityTagsQuery();

  if (hightqualityTags && hightqualityTags.tags) {
    const exist = hightqualityTags.tags.find((tag) => tag.name === currentTag);

    if (currentTag === initialTag) {
      setBannerVisibility(true);
    } else {
      setBannerVisibility(!!exist);
    }
  }

  return (
    <div>
      {bannerVisibility && <HighqualityBanner />}
      <Catlist
        initialTag={initialTag}
        tag={currentTag}
        onSelectTag={onSelectTag}
      />
      <div>
        <PlaylistItem />
      </div>
    </div>
  );
};

api

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const musicApi = createApi({
  reducerPath: "musicApi",
  baseQuery: fetchBaseQuery({
    baseUrl: "https://music-api-33.vercel.app",
  }),
  endpoints: (builder) => ({
    getRecommendBanner: builder.query({ query: () => "/banner" }),
    getPlaylistHotlist: builder.query({ query: () => "/playlist/hot" }),
    getPlaylistCatlist: builder.query({ query: () => "/playlist/catlist" }),
    getPlaylistHighqualityTags: builder.query({
      query: () => "/playlist/highquality/tags",
    }),
  }),
});

export const {
  useGetRecommendBannerQuery,
  useGetPlaylistHotlistQuery,
  useGetPlaylistCatlistQuery,
  useGetPlaylistHighqualityTagsQuery,
} = musicApi;

I want to find currentTag is or isn't existing in the hightqualityTags.tags and according the result to set the banner's visiblity. I'm new to redux-toolkit-query, I try to read the docs but it's hard to me.

CodePudding user response:

too many rerenders occur due to the fact that you change the state of the component every time its state changes in the if() block. I.e., looping occurs.

You need to wrap your if block in useEffect(() => {}) and everything should work out.

const Playlist = () => {
  // tag logic
  const initialTag = "全部歌单";
  const [currentTag, setCurrentTag] = useState(initialTag);

  const onSelectTag = (tag) => {
    setCurrentTag(tag);
  };

  //set banner visibility
  const [bannerVisibility, setBannerVisibility] = useState(true);

  const { data: hightqualityTags } = useGetPlaylistHighqualityTagsQuery();

  useEffect(() => {
    if (hightqualityTags && hightqualityTags.tags) {
      const exist = hightqualityTags.tags.find((tag) => tag.name === currentTag);

      if (currentTag === initialTag) {
        setBannerVisibility(true);
      } else {
        setBannerVisibility(!!exist);
      }
    }
  }, [currentTag, hightqualityTags])

  return (
    <div>
      {bannerVisibility && <HighqualityBanner />}
      <Catlist
        initialTag={initialTag}
        tag={currentTag}
        onSelectTag={onSelectTag}
      />
      <div>
        <PlaylistItem />
      </div>
    </div>
  );
};

Do not allow the state of the component to change outside of functions or events. Remember that React functional components behave like normal functions, i.e. when the state changes, they are executed completely and render() is terminated.

  • Related