Я пытаюсь переписать свое приложение с редукса на новый контекст + хуки, но, к сожалению, мне сложно найти хороший способ справиться с серией синхронных побочных эффектов, которые зависят от реакции предыдущего.
В моем текущем приложении-редуксе я интенсивно использую синхронные / цепочечные действия и запросы API, которые я обычно обрабатываю через redux-saga или thunks. Поэтому, когда возвращается ответ на первый запрос API, эти данные используются для следующего запроса API и т. Д.
Я сделал пользовательский хук «useFetch» (в этом примере он мало что делает, так как это упрощенная версия, также мне пришлось сделать небольшую настройку, чтобы она работала с кодами и боксом - см. Код ниже). Проблема в том, что из-за «правил хуков» я не могу использовать собственный хук внутри хука useEffect. Так как же дождаться ответа на первый запрос, прежде чем делать следующий и т. Д., Если у вас есть собственный хук для извлечения данных? И даже если бы я в конечном итоге отказался от абстракции useFetch и создал ванильный запрос на выборку, как избежать попадания в раздутый беспорядок многих хуков useEffects? Можно ли сделать это немного более элегантно, или контекст + перехватывает все еще преждевременно, чтобы конкурировать с избыточной сагой / толчком для обработки побочных эффектов?
Пример кода ниже очень прост. То, что следует попытаться смоделировать, это:
- запрос человек конечная точка API, чтобы получить человека
- как только у нас появится человек
ответ, запрос конечной точки задания (используя идентификатор человека в реальном мире
сценарий)
- раз у нас есть человек и работа, на основании ответа
от человека и конечных точек работы, запросите конечную точку коллег в
найти лиц коллег по конкретной работе.
Вот код. Добавлена задержка для использования ловушки получения для имитации задержки в реальном мире:
import React, { useEffect, useState } from "react";
import { render } from "react-dom";
import "./styles.css";
const useFetch = (url, delay = 0) => {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
// const result = await fetch(url, {
// method: "GET",
// headers: { "Content-Type": "application/json" }
// });
//const response = await result.json();
const response = await import(url);
setTimeout(function() {
setData(response);
}, delay);
};
fetchData();
}, [url]);
return data;
};
function App() {
const [person, setPerson] = useState();
const [job, setJob] = useState();
const [collegues, setCollegues] = useState();
// first we fetch the person /api/person based on the jwt most likely
const personData = useFetch("./person.json", 5000);
// now that we have the person data, we use the id to query for the
// persons job /api/person/1/jobs
const jobData = useFetch("./job.json", 3000);
// now we can query for a persons collegues at job x /api/person/1/job/1/collegues
const colleguesData = useFetch("./collegues.json", 1000);
console.log(personData);
console.log(jobData);
console.log(colleguesData);
// useEffect(() => {
// setPerson(useFetch("./person.json", 5000));
// }, []);
// useEffect(() => {
// setJob(useFetch("./job.json", 3000));
// }, [person]);
// useEffect(() => {
// setCollegues(useFetch("./collegues.json",1000));
// }, [job]);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Пример выполнения: https://codesandbox.io/s/2v44lron3n?fontsize=14 (может потребоваться внести изменение - пробел или удалить точку с запятой - чтобы оно заработало)
Надеюсь, что-то подобное (или лучшее решение) возможно, или я просто не смогу перейти с удивительной версии redux-saga / thunks на context + hooks.
Лучший ответ: https://www.youtube.com/watch?v=y55rLsSNUiM