From f86409f66559bde28dff8d0e008658d1d9ecd287 Mon Sep 17 00:00:00 2001 From: Andrew Trieu Date: Sat, 24 Jun 2023 17:00:08 +0300 Subject: [PATCH] Upload 6.24 --- part6/query-anecdotes/src/App.js | 11 +++++- .../src/components/AnecdoteForm.js | 20 +++++++++- .../src/components/Notification.js | 24 ++++++------ part6/query-anecdotes/src/index.js | 9 +++-- .../src/reducers/notificationReducer.js | 37 +++++++++++++++++++ 5 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 part6/query-anecdotes/src/reducers/notificationReducer.js diff --git a/part6/query-anecdotes/src/App.js b/part6/query-anecdotes/src/App.js index 8a3acd6..d4f4514 100644 --- a/part6/query-anecdotes/src/App.js +++ b/part6/query-anecdotes/src/App.js @@ -2,9 +2,11 @@ import AnecdoteForm from "./components/AnecdoteForm"; import Notification from "./components/Notification"; import { useQuery, useQueryClient, useMutation } from "react-query"; import { getAnecdotes, updateAnecdote } from "./components/requests"; +import { useNotificationDispatch } from "./reducers/notificationReducer"; const App = () => { const queryClient = useQueryClient(); + const dispatch = useNotificationDispatch(); const mutation = useMutation(updateAnecdote, { onSuccess: (newAnecdote) => { @@ -18,11 +20,18 @@ const App = () => { }, }); - const handleVote = (anecdote) => { + const handleVote = async (anecdote) => { mutation.mutate({ ...anecdote, votes: anecdote.votes + 1, }); + await dispatch({ + type: "SET_NOTIFICATION", + data: `You voted '${anecdote.content}'`, + }); + setTimeout(() => { + dispatch({ type: "CLEAR_NOTIFICATION" }); + }, 5000); }; const { data: anecdotes, status } = useQuery("anecdotes", getAnecdotes, { diff --git a/part6/query-anecdotes/src/components/AnecdoteForm.js b/part6/query-anecdotes/src/components/AnecdoteForm.js index a054e28..f054769 100644 --- a/part6/query-anecdotes/src/components/AnecdoteForm.js +++ b/part6/query-anecdotes/src/components/AnecdoteForm.js @@ -1,19 +1,30 @@ import { useQueryClient, useMutation } from "react-query"; import { createAnecdote } from "./requests"; +import { useNotificationDispatch } from "../reducers/notificationReducer"; const AnecdoteForm = () => { const queryClient = useQueryClient(); + const dispatch = useNotificationDispatch(); const mutation = useMutation(createAnecdote, { onSuccess: (newAnecdote) => { const anecdotes = queryClient.getQueryData("anecdotes"); queryClient.setQueryData("anecdotes", [...anecdotes, newAnecdote]); }, + onError: (err) => { + dispatch({ + type: "SET_NOTIFICATION", + data: `An error occurred: ${err.response.data.error}`, + }); + setTimeout(() => { + dispatch({ type: "CLEAR_NOTIFICATION" }); + }, 5000); + }, }); const getId = () => (100000 * Math.random()).toFixed(0); - const onCreate = (event) => { + const onCreate = async (event) => { event.preventDefault(); const content = event.target.anecdote.value; event.target.anecdote.value = ""; @@ -22,6 +33,13 @@ const AnecdoteForm = () => { id: getId(), votes: 0, }); + await dispatch({ + type: "SET_NOTIFICATION", + data: `You created '${content}'`, + }); + setTimeout(() => { + dispatch({ type: "CLEAR_NOTIFICATION" }); + }, 5000); }; return ( diff --git a/part6/query-anecdotes/src/components/Notification.js b/part6/query-anecdotes/src/components/Notification.js index 443fed8..8bbb200 100644 --- a/part6/query-anecdotes/src/components/Notification.js +++ b/part6/query-anecdotes/src/components/Notification.js @@ -1,18 +1,20 @@ +import { useNotificationValue } from "../reducers/notificationReducer"; + const Notification = () => { const style = { - border: 'solid', + border: "solid", padding: 10, borderWidth: 1, - marginBottom: 5 + marginBottom: 5, + }; + + const notification = useNotificationValue(); + + if (!notification) { + return null; } - - if (true) return null - return ( -
- -
- ) -} + return
{notification}
; +}; -export default Notification +export default Notification; diff --git a/part6/query-anecdotes/src/index.js b/part6/query-anecdotes/src/index.js index e7b7253..b1c09a1 100644 --- a/part6/query-anecdotes/src/index.js +++ b/part6/query-anecdotes/src/index.js @@ -1,13 +1,16 @@ import React from "react"; import ReactDOM from "react-dom/client"; import { QueryClient, QueryClientProvider } from "react-query"; +import { NotificationProvider } from "./reducers/notificationReducer"; import App from "./App"; const queryClient = new QueryClient(); ReactDOM.createRoot(document.getElementById("root")).render( - - - + + + + + ); diff --git a/part6/query-anecdotes/src/reducers/notificationReducer.js b/part6/query-anecdotes/src/reducers/notificationReducer.js new file mode 100644 index 0000000..13a1954 --- /dev/null +++ b/part6/query-anecdotes/src/reducers/notificationReducer.js @@ -0,0 +1,37 @@ +import { createContext, useReducer, useContext } from "react"; + +const notificationReducer = (state, action) => { + switch (action.type) { + case "SET_NOTIFICATION": + return action.data; + case "CLEAR_NOTIFICATION": + return null; + default: + return state; + } +}; + +const NotificationContext = createContext(); + +const NotificationProvider = ({ children }) => { + const [notification, dispatch] = useReducer(notificationReducer, " "); + + return ( + + {children} + + ); +}; + +const useNotificationValue = () => { + const notificationAndDispatch = useContext(NotificationContext); + return notificationAndDispatch.notification; +}; + +const useNotificationDispatch = () => { + const notificationAndDispatch = useContext(NotificationContext); + return notificationAndDispatch.dispatch; +}; + +export { NotificationProvider, useNotificationValue, useNotificationDispatch }; +export default NotificationContext;