我正在尝试使用自定义挂钩来调用API以获取数据。然后我尝试在我的上下文API中调用那个钩子。问题是钩子的主体被渲染了6次。因此,当我尝试使用自定义钩子(useFetchData(返回的数据在上下文文件中设置State时,我会得到错误-";错误:重新渲染过多。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反复渲染
错误当我取消注释{//setState({track_list:data,heading:"Top 10 Tracks",loading}(//导致过多的重新渲染。}上下文文件中的这一行
setState({ track_list: data, heading: "Top 10 Tracks", loading })
会导致无限数量的重新渲染,因为您是在组件的主体中设置它,而不是响应某些东西,例如处理程序或效果。所以,每次设置状态时,都会产生一个渲染,然后重新设置状态,导致另一个渲染。
在提供程序中添加useEffect
以检测对相关数据的更改,并在其中设置状态。类似
useEffect(() => {
setState({ track_list: data, heading: "Top 10 Tracks", loading })
}, [loading, data])
只有当loading
或data
与上次渲染不同时,才会调用此选项。