Created
June 22, 2020 19:48
-
-
Save technolaaji/4c77f39663c67b783247b6e842bc2ec7 to your computer and use it in GitHub Desktop.
React Hooks - Redux Example and Context Example for Hooks
This file contains 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
Here is an small example of the issues I face when using Redux and Redux Toolkit with other libraries hooks | |
keep in mind that it is something I have been facing for quite some time, if you have a better solution then go ahead I am all ears here (really) | |
maybe I am not using Redux properly or misusing it or there might be a better way of handling this situation but I am up for feedback and suggestions | |
hooks like useNavigate from @reach/router or toast from react-toastify expect to be found within a Provider (which is expected) | |
my coding pattern is that when I write my dispatch functions, I tend to write them away from the component and import it as a single function | |
that perform everything under the hood, keeping my components more readable and clean to look at | |
typically I would use useDispatch from react-redux and create a dispatch function and pass it as a reference inside of that function | |
the example that I am going to provide is a function that updates your availability and sends a toast when it successfully updates | |
first I will create a slice (using Redux Toolkit) so the slice will be like the following: | |
const availableSlice = createSlice( | |
name: 'Available Slice', | |
initialState: { | |
status: true | |
}, | |
reducer: { | |
update(state,action){ | |
state.status = action.payload | |
} | |
} | |
); | |
then I created my useDispatch and toast hook inside of my component | |
consider that I have already configured my http library of choice with all the authorization configuration and interceptors (here it is axios) | |
now that function that will dispatch this action, I pass the dispatch and the toast as a reference in the function so like this | |
const updateAvailability = async(dispatch, toast) => { | |
const response = await axios.post('/user/availability'); | |
if(response.data.statusCode){ | |
toast('Availability updated successfully!'); | |
dispatch(availableSlice.actions.update(response.data.status)); | |
} | |
else { | |
toast('Something wrong happened, please try again later'); | |
} | |
} | |
inside of my component I would call this function and use it | |
// inside component of choice | |
import { toast } from 'react-toastify'; | |
import { useDispatch } from 'react-redux'; | |
const dispatch = useDispatch(); | |
const triggerUpdateAvailability = async () => { | |
// the function we created earlier | |
await updateAvailability(dispatch, toast); | |
} | |
Another thing I have been doing that I feel that is quite of a hack is importing the store and dispatching from it directly | |
so the previous will look like this | |
const updateAvailability = async(toast) => { | |
const response = await axios.post('/user/availability'); | |
if(response.data.statusCode){ | |
toast('Availability updated successfully!'); | |
store.dispatch(availableSlice.actions.update(response.data.status)); | |
} | |
else { | |
toast('Something wrong happened, please try again later'); | |
} | |
} | |
I have tried the store.dispatch and it served me well in some projects but I feel it is a bit hacky so I prevent using it but it saves me from importing the dispatch hook everytime I need to dispatch | |
the context version is a bit smoother and easier for me in my perspective so it looks more like this: | |
import React, {useContext, createContext, useState } from 'react' | |
import axios from 'axios' | |
import { toast } from 'react-toastify' | |
const AvailableContext = createContext(null); | |
const AvailableProvider = ({ children }) => { | |
const [availabilty, updateAvailabilty] = useState(true); | |
const update = async () => { | |
const response = await axios.post('/user/availability'); | |
if(response.data.statusCode){ | |
toast('Availability updated successfully!'); | |
updateAvailabilty(response.data.status); | |
} | |
else { | |
toast('Something wrong happened, please try again later'); | |
} | |
} | |
return <AvailableContext.Provider value={[availabilty, update]}> {children} </AvailableContext> | |
} | |
const useUpdateAvailabilty = () => { | |
const context = useContext(AvailabiltyContext); | |
if(context === null || context === undefined){ | |
throw new Error('useUpdateAvailabilty must be found within a AvailableProvider'); | |
} | |
return context; | |
} | |
now in my app I just need to import that hook and use it so like this: | |
const [availabilty, update] = useUpdateAvailabilty(); | |
const triggerUpdateAvailability = async () => { | |
await update(); | |
} | |
the context version does require some extra setup but I feel that it is a bit clear and easier to work with other hook functions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment