我正在尝试使用自定义钩子来调用API来获取数据。然后,我尝试在我的Context API中调用该钩子。问题在于,钩子的主体被渲染了6次。因此,当我尝试使用自定义钩子(useFetchData)返回的数据在Context文件中设置setState时,出现错误-“错误:重新渲染太多。React限制了渲染数量,以防止无限循环。” 。我认为某些状态更改导致其重新呈现。
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(自定义挂钩)
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;
浏览器日志
useFetchData.js:7一次又一次渲染
useFetchData.js:7一次又一次渲染
useFetchData.js:16 {track_list:Array(5)}
useFetchData.js:7一次又一次渲染
useFetchData.js:7一次又一次渲染
useFetchData.js:7一次又一次渲染
useFetchData.js:7一次又一次渲染
答案 0 :(得分:3)
setState({ track_list: data, heading: "Top 10 Tracks", loading })
导致无限次重新渲染,因为您将其设置在组件主体中,而不是响应某些内容,例如处理程序或效果。因此,每次您设置状态时,都会生成一个渲染,然后重新设置状态,从而导致另一个渲染,即无穷无尽。
在提供者中添加useEffect
,以检测对相关数据的更改并在那里设置状态。像
useEffect(() => {
setState({ track_list: data, heading: "Top 10 Tracks", loading })
}, [loading, data])
仅当loading
或data
与上次渲染不同时才会调用此方法。