Skip to content

Instantly share code, notes, and snippets.

@hitrik
Last active July 25, 2019 15:33
Show Gist options
  • Save hitrik/d31027b18b2c898a6d81ea8fff1c4c56 to your computer and use it in GitHub Desktop.
Save hitrik/d31027b18b2c898a6d81ea8fff1c4c56 to your computer and use it in GitHub Desktop.
//wrapper for react tree with multi fetch
import React, { useState, useEffect, useMemo } from "react";
const apiUrl = `https://jsonplaceholder.typicode.com`;
const isValid = (checker, ...args) =>
args.filter(checker).length === args.length;
const fetch = async ({ url, ...options }) => {
try {
console.log(url, options);
const response = await window.fetch(apiUrl + url, options);
const json = await response.json();
return json;
} catch (error) {
console.log("ERROR", error);
throw error;
}
};
const StoreContext = React.createContext();
const initialState = {
users: [],
posts: [],
comments: []
};
const reducer = (state, action) => {
return { ...state, ...action.payload };
};
const Store = props => {
const [store, dispatch] = React.useReducer(reducer, initialState);
const [renderer, setRenderer] = useState("Loading...");
const [errorUsers, users] = useFetch("/users");
const [errorComments, comments] = useFetch("/comments");
const [errorPosts, posts] = useFetch("/posts");
const errorMessage = useMemo(() => {
const error = errorUsers || errorPosts || errorComments;
return JSON.stringify(error && error.message);
}, [errorUsers, errorPosts, errorComments]);
useEffect(() => {
const noErrors = isValid(
a => a === null,
errorUsers,
errorPosts,
errorComments
);
const correctData = isValid(
a => Array.isArray(a) && a.length > 0,
users,
posts,
comments
);
if (!noErrors) {
const Error = props.error;
setRenderer(<Error message={errorMessage} />);
}
if (noErrors && correctData) {
dispatch({ payload: { users, posts, comments } });
setRenderer(props.children);
}
}, [users, posts, comments, errorMessage]);
return (
<StoreContext.Provider value={{ ...store, dispatch }}>
{renderer}
</StoreContext.Provider>
);
};
const useFetch = url => {
const [data, setData] = useState([]);
const [error, setError] = useState(null);
useEffect(() => {
fetch({
url,
headers: {
"Content-type": "application/json"
}
})
.then(setData)
.catch(setError);
}, []);
return [error, data];
};
export { useFetch, Store, StoreContext };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment