'Infinite loop in React with useReducer
I am trying to use useReducer hook to maintain state. When my page is scrolled, I want to apply a set of styles and when I click a button I want to revert to initial styles .But for some reason I keep running into an infinite loop and cannot figure where I went wrong. Any help is appreciated.
import React, { useReducer, useEffect, useState } from "react";
import Navigation from "./Navigation";
import SearchFilter from "./SearchFilter";
const initial = {
searchFilter: "scale-100 bottom-0",
navItems: "scale-y-100 scale-x-100 duration-500 top-1/4",
background: "h-40 bg-black",
searchBox: "opacity-0 scale-110",
};
function FinalNavigation() {
const navReducer = (state, action) => {
switch (action.type) {
case "normal":
return {
...state,
searchFilter: "scale-100 bottom-0",
navItems: "scale-y-100 scale-x-100 duration-500 top-1/4",
background: "h-40 bg-black",
searchBox: "opacity-0 scale-110",
};
case "scrolled":
return {
...state,
searchFilter: "scale-0 bottom-1/2",
navItems: "scale-y-0 scale-x-0 duration-500 delay-75",
background: "h-20 bg-slate-100",
searchBox: "opacity-100 scale-100 duration-500 delay-75",
};
}
};
const [style, dispatch] = useReducer(navReducer, initial);
return (
<>
{console.log(style)}
<div
className={ ${style.background} `}
>
<Navigation
searchTransform={style.searchBox}
navTransform={style.navItems}
searchClick={dispatch({ type: "scrolled" })}
/>
<div
className={`${style.searchFilter}`}
>
<SearchFilter />
</div>
</div>
<button
onClick={dispatch({ type: "normal" })}
>
Click Me
</button>
</>
);
}
export default FinalNavigation;
Solution 1:[1]
const handleOnSearch = () => dispatch({ type: "scrolled" })
const handleOnClick = () => dispatch({ type: "normal" });
return (
<>
{console.log(style)}
<div
className={ ${style.background} `}
>
<Navigation
searchTransform={style.searchBox}
navTransform={style.navItems}
searchClick={handleOnSearch}
/>
<div
className={`${style.searchFilter}`}
>
<SearchFilter />
</div>
</div>
<button
onClick={handleOnClick}
>
Click Me
</button>
</>
);
Would that work?
Basically, in your code dispatch is being called as soon as you render the component. And triggers and updates of the state, that triggers a new render, and hence an infinite loop.
You want to declare the function but only call it in response to the event. That is why you need to wrap it in an arrow function and only call dispatch when the event is called. Exactly what Kevin said above in comments.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
