简体   繁体   中英

Component being rendered 6 times in react

I am trying to use a custom hook to call the API for fetching data. And then I am trying to call that hook in my Context API. The problem is that the body of the hook is being rendered 6 times. So then when I try to setState in my Context file using the data returned by the custom hook(useFetchData), I get the error - "Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.". I think some state change is causing it to re-render.

context.js

import React, { useState, createContext } from "react";
import useFetchData from './Custom Hooks/useFetchData'

export const Context = createContext();

export function Provider(props) {
  let intialState = {
    track_list: [],
    heading: "",
    loading: true
    // dispatch: action => this.setState(state => reducer(state, action))
  };

  const [state, setState] = useState(intialState)

  // Get Top 10 Tracks
  const url = 'chart.tracks.get?chart_name=top&page=1&page_size=5&country=it&f_has_lyrics=1'
  const [data, loading] = useFetchData(url)
  // setState({ track_list: data, heading: "Top 10 Tracks", loading })  // Causes Too Many Re-renders.
  return (
    <Context.Provider value={[state, setState]}>{props.children}</Context.Provider>
  );
}

useFetchData (Custom Hook)

import { useState, useEffect } from "react";
import axios from "axios";

function useFetchData(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  console.log('Rendering Again and Again');
  useEffect(() => {
    // Top 10 Tracks
    async function fetchData(url) {
      try {
        const response = await axios.get(
          `${url}&apikey=${process.env.REACT_APP_API_KEY}`
        );
        const data = await response.data.message.body;
        console.log(data);
        setData(data);
        setLoading(false);
      } catch (error) {
        console.log(error);
      }
    }

    fetchData(url);
  }, [url]);

  return [data, loading];
}

export default useFetchData;

Browser Logs

useFetchData.js:7 Rendering Again and Again

useFetchData.js:7 Rendering Again and Again

useFetchData.js:16 {track_list: Array(5)}

useFetchData.js:7 Rendering Again and Again

useFetchData.js:7 Rendering Again and Again

useFetchData.js:7 Rendering Again and Again

useFetchData.js:7 Rendering Again and Again

Error When I uncomment {// setState({ track_list: data, heading: "Top 10 Tracks", loading }) // Causes Too Many Re-renders.} this line in context file

setState({ track_list: data, heading: "Top 10 Tracks", loading }) is causing an infinite number of re-renders because you're setting it in the body of the component, not in response to something, eg, a handler or an effect. So, each time through you're setting state, which results in a render, which then re-sets state, causing another render, ad infinitum.

Add a useEffect in your provider to detect changes to the relevant data and set the state there. Something like,

useEffect(() => {
    setState({ track_list: data, heading: "Top 10 Tracks", loading })
}, [loading, data])

This will only be called when loading or data is different than the last render.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM