In a MERN stack app, I'm trying to fetch data from two Mongodb databases and store them in context state, but I can only ever get one or the other depending on the order they are in.
App.js
. In this case, the second useEffect
hook works but not the first.
import { useEffect } from 'react';
import { useClosetContext } from './hooks/useClosetContext';
function App() {
const { dispatch } = useClosetContext()
useEffect(() => {
const fetchCloset = async () => {
const response = await fetch('/api/closet')
const json = await response.json()
if (response.ok) {
dispatch({type:'SET_CLOSET', payload: json})
}
}
fetchCloset()
}, [dispatch])
useEffect(() => {
const fetchSavedLists = async () => {
const response = await fetch('/api/checklist')
const json = await response.json()
if (response.ok) {
dispatch({type:'SET_CHECKLISTS', payload: json})
}
}
fetchSavedLists()
}, [dispatch])
return (
<div className="App">...</div>
);
}
export default App;
I have tried putting both the fetchCloset()
and fetchSavedLists()
functions in the same useEffect
hook, but I get the same results.
I also tried this, but didn't get anything:
useEffect(() => {
const fetchData = () => {
Promise.all([
fetch('/api/closet'),
fetch('/api/checklist')
]).then(([closet, checklist]) => {
dispatch({type:'SET_CLOSET', payload: closet})
dispatch({type:'SET_CHECKLISTS', payload: checklist})
}).catch(err => {
console.log(err)
})
}
fetchData()
}, [dispatch])
Here is my Context file:
import { createContext, useReducer } from "react";
export const ClosetContext = createContext()
export const closetReducer = (state, action) => {
switch (action.type) {
case 'SET_CLOSET':
return {
closet: action.payload
}
case 'CREATE_GEAR':
return {
closet: [action.payload, ...state.closet]
}
case 'SET_CHECKLISTS':
return {
checklists: action.payload
}
case 'CREATE_CHECKLIST':
return {
checklists: [action.payload, ...state.checklists]
}
default:
return state
}
}
export const ClosetContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(closetReducer, {
closet: null,
checklists: null
})
return (
<ClosetContext.Provider value={{...state, dispatch}}>
{ children }
</ClosetContext.Provider>
);
}
Context Hook:
import { useContext } from "react";
import { ClosetContext } from "../context/ClosetContext";
export const useClosetContext = () => {
const context = useContext(ClosetContext)
if (!context) {
throw Error('error')
}
return context
}
I don't think there is anything wrong with the backend because I can fetch the data separately. Is there any way I can fetch both databases and set them to Context state?
CodePudding user response:
The problem is in your reducer:
case 'SET_CLOSET':
return {
closet: action.payload
}
case 'SET_CHECKLISTS':
return {
checklists: action.payload
}
You may want something like:
case 'SET_CLOSET':
return {
...state,
closet: action.payload
}
case 'SET_CHECKLISTS':
return {
...state,
checklists: action.payload
}
Otherwise SET_CLOSET
will erase checklists
and SET_CHECKLISTS
will erase closet
.