Issue
im using the useContext from react , i have add boolean state to context but when i use it in the component it's give me typeErro : the setState is not a function
what im doing wrong this is my code ?
// context file
import { createContext, useContext, Dispatch, SetStateAction } from 'react';
interface TasksContextType {
isSubmitLoading: boolean;
setIsSubmitLoading: Dispatch<React.SetStateAction<boolean>>;
}
export const TasksContext = createContext({} as TasksContextType);
export const useTasksContext = () => {
const context = useContext<TasksContextType>(TasksContext);
if (!context) {
throw new Error('useTasksContext should be used within a TasksContext');
}
return context;
};
the provider file
//provider file
import React, { FC, useState } from 'react';
import { TasksContext } from './TasksContext';
export const TasksProvider: FC = ({ children }) => {
const [isSubmitLoading, setIsSubmitLoading] = useState<boolean>(false);
return (
<TasksContext.Provider
value={{
isSubmitLoading,
setIsSubmitLoading,
}}
>
{children}
</TasksContext.Provider>
);
};
the component where i use the useContext
//component
const { setIsSubmitLoading, isSubmitLoading } = useTasksContext();
useEffect(() => {
setIsSubmitLoading(mutation.isLoading);
}, [mutation, setIsSubmitLoading]);
Solution
Here's an example based on the code you provided so you can see that it works and how to use it (more explanation below):
<div id="root"></div><script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.17.6/babel.min.js"></script><script>Babel.registerPreset('tsx', {presets: [[Babel.availablePresets['typescript'], {allExtensions: true, isTSX: true}]]});</script>
<script type="text/babel" data-type="module" data-presets="tsx,react">
// import ReactDOM from 'react-dom';
// import {
// default as React,
// createContext,
// useContext,
// useEffect,
// useState,
// type Dispatch,
// type ReactElement,
// type ReactNode,
// type SetStateAction,
// } from 'react';
// This Stack Overflow snippet demo uses UMD modules instead of the above import statments
const {
createContext,
useContext,
useEffect,
useState,
} = React;
type TasksContextType = {
isSubmitLoading: boolean;
setIsSubmitLoading: Dispatch<SetStateAction<boolean>>;
};
const TasksContext = createContext(undefined as unknown as TasksContextType);
function useTasksContext (): TasksContextType {
return useContext<TasksContextType>(TasksContext);
}
function TasksProvider ({children}: { children?: ReactNode }): ReactElement {
const [isSubmitLoading, setIsSubmitLoading] = useState(false);
return (
<TasksContext.Provider
value={{
isSubmitLoading,
setIsSubmitLoading,
}}
>{children}</TasksContext.Provider>
);
}
function App (): ReactElement {
const {isSubmitLoading, setIsSubmitLoading} = useTasksContext();
useEffect(() => {
setTimeout(() => setIsSubmitLoading(true), 1500);
}, [setIsSubmitLoading]);
const handleClick = () => setIsSubmitLoading(bool => !bool);
return (
<div style={{fontFamily: 'sans-serif'}}>
<h1>Using the Context API</h1>
<div>
<pre>
<code>
{JSON.stringify({isSubmitLoading}, null, 2)}
</code>
</pre>
</div>
<button onClick={handleClick}>Toggle state</button>
</div>
);
}
function AppRoot (): ReactElement {
return (
<TasksProvider>
<App />
</TasksProvider>
);
}
ReactDOM.render(<AppRoot />, document.getElementById('root'));
</script>
You didn't show in your code where you actually use the ContextProvider and the JSX structure of your app, but it's important that you only use useTasksContext
in components that are rendering inside the Provider root. In the example above, I created a component dedicated to rendering the Provider so that it's out of the way and in the main App
component, you can just focus on the code.
Answered By - jsejcksn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.