useContext returns 值多次,仅调用 1 次

useContext returns values multiple times when called only 1 time

我想从 API 获取数据并将其存储在 context 中,以便在多个组件上使用该数据。此 API 有多个端点,我需要用户 ID 才能访问它们。为此,我从 useParams 获取 id,并使用上下文传递的挂钩 setID 更改 id。

问题是:当我console.log更改ID后的数据时,控制台显示4个不同的数据,在useEffect中一步一步显示:

但是我只是在useEffect回调中设置了id,所以我不明白为什么它会在值更改1次时触发4次。

我不知道我这样做的方式是否正确(如果使用上下文在那里是一件坏事),或者只是我误解了 useEffect 和 useContext。

// Component receiving the data
function APIChecker(){
    const {id} = useParams();
    const data = useContext(DataContext);
    data.setID(id);
    
    console.log(data);

    return(
        <>
        </>
    );
}

export default APIChecker;
// Context
export const DataContext = React.createContext();

export const DataProvider = ({children}) => {
    const [id, setID] = useState(null);

    const initialData = {
        globalInfo: [],
        activity: [],
        averageSession: [],
        performance: []
    }

    const [data, setData] = useState(initialData);
    const [error, setError] = useState(404);

    useEffect(() => {
        const url = "http://localhost:3000/user/";
        const fetchData = async () =>{
            Promise.all([
                fetch(url + id),
                fetch(url + id + "/activity"),
                fetch(url + id + "/average-sessions"),
                fetch(url + id + "/performance")
            ]).then(([responseGlobal, responseActivity, responseSessions, responsePerformance]) => Promise.all([responseGlobal.json(), responseActivity.json(), responseSessions.json(), responsePerformance.json(), responseGlobal.status
            ])).then(([responseGlobal, responseActivity, responseSessions, responsePerformance, statusError]) => {
                setError(statusError);
                setData({
                    globalInfo: responseGlobal,
                    activity: responseActivity,
                    averageSessions: responseSessions,
                    performance: responsePerformance
                });
            }).catch(error => {
                throw new Error(error);
            });
        }
        if(id != null){
            fetchData();
        }

    }, [id])

    return(
        <DataContext.Provider value={{id, data, setID, error}}>
            {children}
        </DataContext.Provider>
    )
}

每次您的子组件 APIChecker 调用 setID 时,这将触发父组件中的 useEffect,因为您已在依赖数组中传递了 id。 这反过来会多次调用 API。

useEffect(()=>{
    /*your implementation*/
},[id]);

如果你只想调用一次,只需传递空数组作为依赖项,如下所示:

useEffect(()=>{
    /*your implementation*/
},[]);