Last active
May 20, 2023 23:05
-
-
Save rnkoaa/a40f3235a6d8e0fad502f41c1df712e5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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