I'm using a hook to fetch data in my app. The hook looks something like this:
const initialState = {
response: null,
loading: true,
error: null
}
const useGetFetch(url, token, user, parser) => {
const [state, dispatch] = useReducer(fetchReducer, initialState)
useEffect (() => {
if(user){
fetch(...)
.then((data)=> data.json())
.then(dispatch(...)) // setting the state here
.catch((error) => dispatch(...)) // set error state
}
}, [user])
return [state.response, state.loading, state.error]
}
Specifically, I'm using this hook inside a form component, to fetch some data to use as options inside a select element.
However, I need to be able to let the user to add new options on the fly. To facilitate this, I've created a button next to the select element. If the user presses this button, a modal will pop up with another form that makes it possible create a new option. This new option is sent to the server via a post request and if successful the modal closes.
The problem I'm facing is that after the modal closes, I have no way of updating the initial data fetched with my custom data fetching hook, unless I refresh the page. Is there a way to make this happen somehow without triggering a page refresh?
My initial hunch was to use a callback function and pass it to the the useGetFetch and bind it to the useEffect hook. I could then pass it to the form in the modal and call the function after a successful submission, but this hasn't worked.
Another option I'm looking is the useCallback hook, but I don't currently understand it well enough to know whether or not it could be helpful.
EDIT
Specifically what I did was create a trigger function outside the parent component:
const trigger = () => console.log("click")
Bound it to the fetch hook:
const useGetFetch(url, token, user, parser, trigger) => {
const [state, dispatch] = useReducer(fetchReducer, initialState)
useEffect (() => {
if(user){
fetch(...)
.then((data)=> data.json())
.then(dispatch(...)) // setting the state here
.catch((error) => dispatch(...)) // set error state
}
}, [user, trigger])
return [state.response, state.loading, state.error]
}
And passed it to the child component inside the parent component:
const trigger = () => console.log("click")
const Parent = () => {
// load a bunch of stuff
// ...
const { show, toggle } = useModal()
const [optionsData, Loading, Error] = useGetFetch(
optionsUrl,
token,
user,
parser,
trigger
)
// ...
return (
<div>
{// ...}
<button
onClick={(e) => {
e.preventDefault()
toggle()
}}
>
Add
</button>
<Modal show={show} toggle={toggle}>
<ModalForm
show={show}
toggle={toggle}
trigger={trigger}
></ModalForm>
</Modal>
{// ...}
<div>
)
}
Inside ModalForm trigger is called after a successful post request has been performed. After closing the modal, the data is not updated. My guess was that calling trigger inside ModalForm would have triggered useEffect inside of the useGetFetch but it doesn't seem to work like that.