Skip to content

Instantly share code, notes, and snippets.

@rnkoaa
Last active May 20, 2023 23:05
Show Gist options
  • Save rnkoaa/a40f3235a6d8e0fad502f41c1df712e5 to your computer and use it in GitHub Desktop.
Save rnkoaa/a40f3235a6d8e0fad502f41c1df712e5 to your computer and use it in GitHub Desktop.
import React, { useReducer, useEffect, useContext, createContext } from "react";
import "./App.css";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useParams,
} from "react-router-dom";
const initialPosts = [];
const PostContext = createContext(initialPosts);
const Store = (props) => {
const [state, dispatch] = useReducer(postsReducer, initialPosts);
return (
<PostContext.Provider value={{ state, dispatch }}>
{props.children}
</PostContext.Provider>
);
};
function App() {
return (
<Store>
<Router>
<Switch>
<Route exact path="/" component={Posts} />
<Route exact path="/posts" component={Posts} />
<Route exact path="/posts/:id" component={PostDetails} />
</Switch>
</Router>
</Store>
);
}
const fetchPosts = async () =>
fetch("https://my-json-server.typicode.com/typicode/demo/posts");
const Posts = () => {
const context = useContext(PostContext);
const { state: posts, dispatch } = context;
useEffect(() => {
const fetchData = async () => {
const result = await fetchPosts();
const data = await result.json();
dispatch({
type: "new",
payload: data,
});
};
if (!posts || posts.length <= 0) {
fetchData();
}
}, [dispatch, posts]);
return (
<>
{posts &&
posts.map((p) => (
<div key={p.id}>
<Link to={`/posts/${p.id}`}>{p.title}</Link>
</div>
))}
</>
);
};
const PostDetails = () => {
const { id } = useParams();
const post = usePost(id);
return post ? <div>{post.title}</div> : <div>No Post Found</div>;
};
function usePost(postId) {
const { state: posts, dispatch } = useContext(PostContext);
const item = posts.find((p) => p.id === parseInt(postId));
useEffect(() => {
const fetchData = async () => {
const result = await fetchPosts();
const data = await result.json();
dispatch({
type: "new",
payload: data,
});
};
if ((!posts || posts.length <= 0) && !item) {
fetchData();
}
}, [dispatch, posts, item]);
return item;
}
function postsReducer(state, action) {
switch (action.type) {
case "new":
return state.concat(action.payload);
case "add":
return [...state, action.payload];
default:
return state;
}
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment