Как я должен сделать пользовательский крюк реакции, если мне нужно отправлять запросы на множество конечных точек?

#reactjs #react-hooks

Вопрос:

Мне нужно отправить GET запросы и POST запросы на многие конечные точки.

Например, GET | POST Список Фруктов GET | POST , Список Погоды…

Не на одной странице, они разделены(Маршрут браузера). например) Страница Фруктов, Страница Погоды…

Я хотел бы знать, как сделать так, чтобы пользователь реагировал в этой ситуации.

Я много искал, но все записи были основаны на одной конечной точке api.


Способ 1

Создайте повторно используемую функцию выборки.

 function useGetFetch(url){
    const response = await fetch(url, ...
    return response.json()
}

function usePostFetch(url){
    const response = await fetch(url, ...
    return response.json()
}
 

Способ 2

Создайте функцию по одной для каждого.

 function getFruitList(){
    const response = await fetch('/fruit', ...
}

function postFruitList(){
    const response = await fetch('/fruit', ...
}

function getWeatherList(){
    const response = await fetch('/weather', ...
}

function postWeatherList(){
    const response = await fetch('/weather', ...
}
 

Комментарии:

1. На мой взгляд, даже если второй способ может показаться менее СУХИМ , он будет лучше масштабироваться и его будет легче поддерживать. Вы можете создать «уровень обслуживания», где мы сохраняем эти различные функции выборки, которые вызываются из a useEffect в маршруте/компоненте, в котором они необходимы. Первый способ может выглядеть хорошо, потому что в нем меньше кода, но при таком подходе вы обязуетесь всегда связывать все конечные точки вместе по этому пути, что может привести к проблемам в будущем.

2. то, что я сделал однажды, — это завернул fetch , чтобы разместить варианты, которые я должен был разместить. если вам нужна информация о пользователе и вы используете контекстный api, использование крючка позволяет легко использовать пользователя из контекста.

3. @AlexanderNied Основываясь на вашем мнении, я думаю, что чем больше конечных точек, тем более управляемый способ2. Спасибо вам за ваше мнение.

4. Добро пожаловать-объединение этого с подходом @Noriller к абстрагированию фактических битов выборки в крючок, вероятно, даст вам лучшее из обоих миров (возможность повторного использования общих частей без ненужной связи). Удачи, счастливого кодирования!

Ответ №1:

Я как-то читал о useAsync крюке Кента и думаю, что ваш второй подход подойдет хорошо. Вот весь код того, что входит в создание многоразового useAsync хука с помощью примера API star-wars :-

 import "./styles.css";
import React, { useEffect } from "react";
export default function App() {
  const {
    run: starShipExec,
    status: starshipStatus,
    data: starshipData,
    error: startshipError
  } = useAsync({ status: "idle" });
  const {
    run: peopleExec,
    status: peopleStatus,
    data: peopleData,
    error: peopleError
  } = useAsync({ status: "idle" });

  useEffect(() => {
    starShipExec(getStarships());
    peopleExec(getPeople());
  }, [starShipExec, peopleExec]);

  return (
    <div className="App">
      Startships
      <ul>
        {starshipData?.results.map((res) => (
          <li>{res.name}</li>
        ))}
      </ul>
      People
      <ul>
        {peopleData?.results.map((res) => (
          <li>{res.name}</li>
        ))}
      </ul>
    </div>
  );
}

async function getStarships() {
  return await fetch("https://swapi.dev/api/starships");
}

async function getPeople() {
  return await fetch("https://swapi.dev/api/people");
}

function asyncReducer(_state, action) {
  switch (action.type) {
    case "pending": {
      return { status: "pending", data: null, error: null };
    }
    case "resolved": {
      return { status: "resolved", data: action.data, error: null };
    }
    case "rejected": {
      return { status: "rejected", data: null, error: action.error };
    }
    default: {
      throw new Error(`Unhandled action type: ${action.type}`);
    }
  }
}

function useSafeDispatch(dispatch) {
  const mountedRef = React.useRef(false);
  React.useLayoutEffect(() => {
    mountedRef.current = true;
    return () => (mountedRef.current = false);
  }, []);

  const safeDispatch = React.useCallback(
    (...args) => {
      mountedRef.current amp;amp; dispatch(...args);
    },
    [dispatch]
  );
  return safeDispatch;
}

function useAsync({ status }) {
  const [state, unsafeDispatch] = React.useReducer(asyncReducer, {
    status: status,
    data: null,
    error: null
  });
  const dispatch = useSafeDispatch(unsafeDispatch);

  const run = React.useCallback(
    (promise) => {
      if (!promise) {
        return;
      }
      dispatch({ type: "pending" });
      promise
        .then((data) => data.json())
        .then((data) => {
          dispatch({ type: "resolved", data });
        })
        .catch((error) => {
          dispatch({ type: "rejected", error });
        });
    },
    [dispatch]
  );

  return { ...state, run };
}

 

Та часть, которая мне нравится, возвращает run функцию, в которую мы можем передать любое обещание, а остальное управляет крючок. Это дает пользователю API больше контроля над тем, что выполнять.

Вот рабочий код и коробка :-

Редактировать useAsync-звездные войны