Привет! В этом блоге мы попытаемся избавиться от useEffect
при начальном рендеринге с помощью react-router
. React router v6 выпустил несколько новых крутых хуков, которые помогут упростить процесс загрузки данных и отправки форм. Спасибо команде Ремикс.
Как упоминалось командой React: UseEffect предназначен для synchronisation
, а не для lifecycle methods
.
В нашем приложении для реагирования мы обычно вызываем API в useEffect
как пример, приведенный ниже. Но в React 18 этот useEffect вызывается дважды, и некоторые разработчики думают, что это какая-то ошибка в реакции, поскольку это происходит только в режиме разработки, поверьте мне, это не ошибка.
import React, { useState, useEffect } from 'react'; const Homepage = () => { const [data, setData] = useState(null); useEffect(() => { // Fetch the data from the API fetch('https://example.com/api/data') .then((response) => response.json()) .then((json) => setData(json)); }, []); // Return a loading message while the data is being fetched if (data === null) { return <p>Loading...</p>; } // Render the data when it is available return <pre>{JSON.stringify(data, null, 2)}</pre>; }; export default Homepage;
Теперь, чтобы избавиться от этого useEffect
, мы будем использовать хук useLoaderData
, предоставленный react-router
. Этот хук доступен только в v6+. Чтобы использовать силу этого хука, нам нужно изменить способ определения наших маршрутов.
import { createBrowserRouter, defer } from "react-router-dom"; const router = createBrowserRouter([ { path: "/", element: <Homepage/>, loader: async ({ request, params }) => { const data = fetch('https://example.com/api/data') return defer({ results: data, }) }, }, ]);
Всякий раз, когда будет вызываться маршрут /homepage
, будет вызываться функция loader
, и данные, возвращенные из этого запроса, могут использоваться компонентом Homepage
для получения возвращенных данных. Итак, теперь компонент будет выглядеть примерно так:
import React from 'react'; import { useLoaderData } from "react-router-dom"; const Homepage = () => { const data = useLoaderData() // Render the data when it is available return <pre>{JSON.stringify(data, null, 2)}</pre>; }; export default Homepage;
С помощью этого хука теперь мы можем избавиться от useEffect
и useState
. Но сейчас вам будет интересно what if we want to show loader while data is being fetched
. Мы можем использовать компонент Await
, предоставленный react-router
, чтобы показать загрузку. Итак, теперь наш компонент будет выглядеть так:
import React from 'react'; import { useLoaderData, Await } from "react-router-dom"; const Homepage = () => { const data = useLoaderData() // Render the data when it is available return <React.Suspense fallback={<p>Loading data...</p>} > <Await resolve={data.result} errorElement={ <p>Error loading data</p> } > {(result) => ( <pre>{JSON.stringify(results, null, 2)}</pre> )} </Await> </React.Suspense> }; export default Homepage;
Спасибо за прочтение!