So I've been learning to use useContext and useReducer hooks with action/dispatch and whenever I try to use dipatch function from any component, it throws out "Uncaught TypeError: dispatch is not a function" error.. it's been 5 days now:/
I try to access dispatch function in the following manner inside components
// context
import { ModalContext } from "../Context/Contexts/ModalContext";
import { OPEN_IMAGE_MODAL } from "../Context/action.types";
const { dispatch } = useContext(ModalContext);
dispatch({
type: OPEN_IMAGE_MODAL,
payload: { isEnabled: true, imageDetails: { url: doc.url } },
});
Here are the ref files
App.js
import React from "react";
// components
import Nav from "./Components/Nav";
import ImageUploadForm from "./Components/ImageUploadForm";
import ImageGrid from "./Components/ImageGrid";
// context
import { ModalContextProvider } from "./Context/Contexts/ModalContext";
const App = () => {
return (
<div className="App">
<Nav />
<ImageUploadForm />
<ModalContextProvider>
<ImageGrid/>
</ModalContextProvider>
</div>
);
};
export default App;
ModalContext.js (Context & Context Provider creation)
import { createContext, useReducer } from "react";
// reducer
import { modalReducer } from "../Reducers/modalReducer";
// components
import ImageModal from "../../Components/ImageModal";
// creating and exporting context
export const ModalContext = createContext();
const initialState = { isEnabled: false, imageDetails: {} };
export const ModalContextProvider = ({ children }) => {
// for selected/clicked image
const [isEnabled, imageDetails, dispatch] = useReducer(
modalReducer,
initialState
);
return (
<ModalContext.Provider value={{ isEnabled, imageDetails, dispatch }}>
{children}
{isEnabled && <ImageModal />}
</ModalContext.Provider>
);
};
modalReducer.js (reducer fn)
import { OPEN_IMAGE_MODAL, CLOSE_IMAGE_MODAL } from "../action.types";
export const modalReducer = (state, action) => {
switch (action.type) {
case OPEN_IMAGE_MODAL:
return {
...state,
isEnabled: true,
imageDetails: action.payload.imageDetails,
};
case CLOSE_IMAGE_MODAL:
return { ...state, isEnabled: false, imageDetails: {} };
default:
return { ...state };
}
};
CodePudding user response:
I think the useReducer hook just can return 2 arrays, the satate and the dsipatch method.
CodePudding user response:
useReducer
returns an array with exactly two values. You are assuming there is some third value dispatch
, which is actually undefined
. And undefined
is not a function.
Depending on how many values you want to passdown using context you can fix this. I like to pass only two values, one state and one dispatch.
const [state, dispatch] = useReducer(
modalReducer,
initialState
);
return (
<ModalContext.Provider value={{ state, dispatch }}>
{children}
{state.isEnabled && <ImageModal />}
</ModalContext.Provider>
);
In children just extract how you do:
const { dispatch } = useContext(ModalContext);