Can I use useReducer from outside component
React hooks should be called only inside functional components. Hook state is maintained per component instance. If hooks have to be reused, they can be extracted into custom hooks, which are functions that call built-in hooks and are supposed to be called inside functional components:
export const useTotal = () => {
const [total, totalDis] = useReducer((total, action) => {...}, 0);
...
return [total, totalDis];
};
In case there's a need to maintain common state for multiple components it should be maintained in common parent and be provided to children through props:
const Root = () => (
const [total, totalDispatcher] = useTotal();
return <App {...{total, totalDispatcher}}/>
);
const App = props => {
return (
<div>{props.total}</div>
);
};
Or context API:
const TotalContext = createContext();
const Root = () => (
<TotalContext.Provider value={useTotal()}>
<App/>
</TotalContext.Provider>
);
const App = () => {
const [total] = useContext(TotalContext);
return (
<div>{total}</div>
);
};
Related videos on Youtube
punpun
Updated on July 14, 2022Comments
-
punpun almost 2 years
Now I'm trying to use useReducer to created a new way for management state and function but now found the problem is "Hooks can only be called inside of the body of a function component" Is there any way to solve this problem?
// App Component import React from "react"; import { product, productDis } from "./ProductReducer"; //{product} is state, {productDis} is dispatch import { total } from "./TotalReducer"; //{total} is state and i dont need {totalDis} const App = () => { return ( <div> <button onClick={()=>productDis({type:'add',payload:'pen'})}>add</button> {product} {total} </div> ); }; export default App;
// ProductReducer Component import React, { useReducer } from 'react'; import {totalDis} from './TotalReducer' //{totalDis} is dispatch and i dont need {total} export const [product, productDis] = useReducer((state, action) => { switch (action.type) { case "add": { const product_0 = 'pencil' const product_1 = `${action.payload} and ${product_0}` totalDis({ type:'total_add', payload:'250' }) return product_1; } default: return state; } }, []);
// TotalReducer Component import React, { useReducer } from 'react'; export const [total, totalDis] = useReducer((total, action) => { switch (action.type) { case "total_add": { const vat = action.payload*1.15 return vat; } default: return total; } }, 0)
when i click the button on display It should be shown..." pen and pencil 287.5 "
but it show "Hooks can only be called inside of the body of a function component"
there any way to solve this problem? or i should back to nature?
-
Tholle about 5 yearsYou can't use
useReducer
outside of a function component, but you can put the reducer function and initial state outside of it if you prefer, like the example in the documentation.
-
-
Artem P over 3 yearsI like how React devs decided that you shouldn't be doing like this and you should do like that. Makes no sense why both ways didn't work.
-
Bryan Grace about 3 yearsThat's not an answer to the question.
-
Estus Flask about 3 years@BryanGrace Can't say about any question, but it definitely answers the question above - whether useReducer can be used inside the component and what are the workarounds. If you didn't understand something, you could ask for a clarification.