See the snippet below.
By doing this:
React.useState(()=>getInitialState2());
You avoid running the getInitialState2()
used in the useState
on every render.
But that doesn't seem to work on the useReducer
hook.
QUESTION
Is there a way to avoid running a function that is used in the initialState
parameter on the useReducer
hook on every render?
function App() {
const [state,dispatch] = React.useReducer(reducer,getInitialState());
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
You are running it on every render by calling it. To make the initialisation lazy, pass a function. In addition, the lazy init is the 3rd param of useReducer
. Whatever you supply as the 2nd param of useReducer
will be passed to the lazy init function, but you can ignore it.
const [state,dispatch] = React.useReducer(reducer, null, getInitialState);
Or wrap it with an arrow function, if you need to initialize it with a value from props:
const [state,dispatch] = React.useReducer(reducer, null, () => getInitialState(props.something));
Demo:
function App() {
const [state,dispatch] = React.useReducer(reducer,null,getInitialState);
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>