У меня реализован следующий код (ПОЖАЛУЙСТА, имейте в виду, я не хочу использовать redux)
Мой глобальный хук хранилища:
// store.tsx - custom store hook
import { useState, useEffect } from "react";
let globalState = {};
let listeners = [];
let actions = {};
export const useStore = () => {
const setState = useState(globalState)[1];
const dispatch = async (actionIdentifier, payload) => { // needed to add async/await in order to wait the async/await in the custom hooks for actions, i.e. for fetching
const newState = await actions[actionIdentifier](globalState, payload);
globalState = { ...globalState, ...newState };
for (const listener of listeners) {
listener(globalState);
}
};
useEffect(() => {
listeners.push(setState);
return () => {
listeners = listeners.filter((li) => li !== setState);
};
}, [setState, shouldListen]);
return [globalState, dispatch];
};
export const initStore = (userActions, initialState) => {
if (initialState) {
globalState = { ...globalState, ...initialState };
}
actions = { ...actions, ...userActions };
};
import { initStore } from "./store";
файл, отвечающий за действия загрузки
// loading-store.tsx
const configureStore = () => {
const actions = {
SET_LOADING_START: (currentState) => {
return { loading: true };
},
SET_LOADING_END: (currentState) => {
return { loading: false };
},
};
initStore(actions, {
loading: false,
});
};
export default configureStore;
и файл, отвечающий за выборку:
// fetching-store.tsx
import { initStore } from "./store";
import { getData } from "src/api/ResourceService";
const configureStore = () => {
function fetchData() {
const fetch = async () => {
try {
const res = await getData();
console.log("[FETCH] Data:", res.data);
return res.data;
} catch (err) {
console.error("[FETCH] Error", err);
return err;
}
};
return fetch();
}
const actions = {
FETCH: async (currentState) => {
const newData = await fetchData();
return { myFetchedData: newData };
},
};
initStore(actions, {
myFetchedData: [],
});
};
export default configureStore;
следующий файл index.tsx:
// index.tsx
import React from "react";
import ReactDOM from "react-dom";
import "./assets/css/simpl-newton-bootstrap.css";
import "../node_modules/react-grid-layout/css/styles.css";
import "../node_modules/react-resizable/css/styles.css";
import { BrowserRouter } from "react-router-dom";
import * as serviceWorker from "./serviceWorker";
import App from "./App";
import { ThemeProvider } from "src/context/ThemeContext";
import fetchingStore from "src/hooks-store/fetching-store";
import loadingStore from "src/hooks-store/loading-store";
fetchingStore();
loadingStore();
ReactDOM.render(
<ThemeProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>,
document.getElementById("root")
);
serviceWorker.unregister();
ВОПРОС: как настроить загрузку на true / false во время выборки, которая выполняется в fetchiing-store.tsx
Это реализация в Компоненте, где я вызываю fetch:
// myComponent.tsx
import React, { useEffect } from "react";
import { useStore } from "src/hooks-store/store";
const myComponent = () => {
const [state, dispatch] = useStore();
const data = state.myFetchedData;
useEffect(() => {
dispatch("FETCH");
}, []);
return (
<>
// some code where data will be used ...
</>
);
}
export default myComponent;
Я пытался поместить ее в useEffect of myComponent.tsx как:
...
useEffect(() => {
dispatch("SET_LOADING_START");
dispatch("FETCH");
}, []);
...
, а затем вручную в fetching-store.tsx
...
const actions = {
FETCH: async (currentState) => {
const newData = await fetchData();
return { myFetchedData: newData, loading: false };
},
};
initStore(actions, {
myFetchedData: [],
loading: false,
});
...
Но это немного грязно. Если у кого-то есть лучшее решение или вариант? Другой вопрос, является ли вообще хорошей идеей использовать вызов async / await в хранилище действий?