Skip to content

Instantly share code, notes, and snippets.

@AamuLumi
Created October 26, 2018 09:53
Show Gist options
  • Save AamuLumi/7e172b3d68a8ee0da4856ce7dcd77988 to your computer and use it in GitHub Desktop.
Save AamuLumi/7e172b3d68a8ee0da4856ce7dcd77988 to your computer and use it in GitHub Desktop.
React Hook to create an internal API Reducer
import React, { Component } from "react";
import { useEffect, useState } from "react";
function createLoadReducer() {
return (state = { loading: false }, action) => {
switch (action.type) {
case "LOADING":
return { loading: true };
case "ERROR":
return { loading: false, error: action.data };
case "SUCCESS":
return { loading: false, data: action.data };
default:
return state;
}
};
}
function useAPIReducer(url, method = "GET", body = {}) {
const internalReducer = createLoadReducer();
const [currentState, setState] = useState(
internalReducer(undefined, { type: "LOADING" })
);
function dispatch(action) {
setState(internalReducer(currentState, action));
}
function fetchData() {
dispatch({ type: "LOADING" });
fetch(url, {
method,
body: method !== "GET" ? JSON.stringify(body) : undefined
})
.then(res => {
if (res.ok) {
return res.json();
}
throw res;
})
.then(data => {
dispatch({ data, type: "SUCCESS" });
})
.catch(res => {
res.text().then(data => {
dispatch({ data, type: "ERROR" });
});
});
}
useEffect(
() => {
fetchData();
},
[url]
);
return [currentState, fetchData];
}
function RedditFetcher(props) {
const [redditPosts, refreshRedditPosts] = useAPIReducer(
"https://www.reddit.com/r/aww/random.json"
);
if (redditPosts.loading) {
return <h1>LOADING...</h1>;
}
if (redditPosts.error) {
return <div>{String(redditPosts.error)}</div>;
}
if (!redditPosts.data) {
return <div>No posts found</div>;
}
return (
<>
<button onClick={refreshRedditPosts}>Refresh</button>
<div>
{redditPosts.data[0].data.children.map((e, i) => (
<>
<h3>{e.data.title}</h3>
<img
key={i}
src={e.data.thumbnail}
style={{ maxWidth: 400, maxHeight: 400 }}
alt={e.data.title}
/>
</>
))}
</div>
</>
);
}
export default RedditFetcher;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment