I use the following code:
The useBaseAxios
hook (the basic hook for queries, will be used inside another custom hook)
import { useState, useEffect} from 'react';
import axios from 'axios';
const baseAxios = axios.create({
baseURL: 'http://127.0.0.1:8000/api/v1',
});
const useBaseAxios = ({ method = "GET", url }) => {
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
const fetchData = async () => {
try {
const response = await baseAxios.request({ method, url, signal })
setData(response.data)
} catch (error) {
if (!axios.isCancel(error)){
setError(error)
}
} finally {
setLoading(false)
}
}
if (!data) {
fetchData()
}
return () => {
controller.abort()
}
}, [method, url])
return [data, isLoading, error]
};
export default useBaseAxios;
The useClosestLesson
hook (uses useBaseAxios
, used in the Main
component)
import useBaseAxios from "./useBaseAxios";
function useClosestLessons() {
const [data, isLoading, error] = useBaseAxios({ method: 'GET', url: '/lessons' })
let lessonsSchedule = [];
let currentLesson = {};
if (data) {
lessonsSchedule = [...data]
currentLesson = lessonsSchedule[0]
}
return [lessonsSchedule, currentLesson, isLoading, error]
}
export default useClosestLessons
The Main
component (when it is rendered, the console logs are displayed)
import React from "react";
import './Main.scss';
import useClosestLessons from "../../hooks/fetch-hooks/useClosestLessons";
import { useState, useEffect, useCallback } from "react";
import axios from "axios";
const Main = () => {
const [lessonsSchedule, currentLessons, isLoading, error] = useClosestLessons();
console.log(lessonsSchedule)
console.log(currentLessons)
if (isLoading) return (<p>Загрузка...</p>)
return(...)
Without using StrictMode
, I expect to receive "null"
, "null"
in the console, then the necessary array and object.
If you return it, I get the following picture:
If I look into profiler, there are 3 renders of Main
component.
Should this be the case, and if so, why?
I only expecting for a detailed explanation of this case is sufficient.
React components rerender for one of two reasons:
The useBaseAxios
state is what appears to be triggering the Main
component to rerender.
I see nothing that would return any null
values.
I also suspect you are actually using the React.StrictMode
component, and if so then the logs make sense to me. The StrictMode
component double-mounts components and double-invokes their render method and various lifecycle methods/hooks, and you are console logging as an unintentional side-effect directly in the component function body, e.g. its "render method".
I see 3 discrete "renders" according to your log output:
"[]"
and "{}"
from the initial mounting * **"[]"
and "{}"
from the double-mount * **lessonsSchedule
, currentLessons
values.* See Fixing bugs found by double rendering in development: Some functions are called twice to help detect impure functions, which includes the component function body top-level logic.
** See Fixing bugs found by re-running Effects in development React will also run one extra setup + cleanup cycle in development.
I think this is mostly just a misunderstanding of your logs and what/how they correlate to the React component lifecycle.