Reputation: 7
i have created a custom React Hook that has a function that will dispatch an action to redux store.
import { useDispatch, useSelector } from "react-redux";
import { toggle } from "../state/reducers/togglePassSlice";
const useToggle = () => {
const { showpass } = useSelector((state) => state.toggle);
const dispatch = useDispatch();
const togglePassVisibility = () => {
// console.log(showpass);
dispatch(toggle(showpass));
};
return { togglePassVisibility };
};
export default useToggle;
on my component when i try to call it, i get an error: Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
import EntryCard from "../../components/EntryCard/EntryCard";
import InputGroup from "../../components/InputGroup/InputGroup";
import Input from "../../components/Input/Input";
import Button from "../../components/Button";
import { EntryPage, PageHader } from "./style";
import { Link } from "react-router-dom";
import useToggle from "../../hooks/useToggle";
const SignInPage = () => {
const { togglePassVisibility } = useToggle();
const toggle = togglePassVisibility();
return (
<EntryPage>
<PageHader to="/">AWESOME LOGO</PageHader>
<EntryCard>
<h2>login</h2>
<form>
<InputGroup>
<label htmlFor="email">Email</label>
<Input type="email" placeholder="Enter email" id="email" />
</InputGroup>
<InputGroup>
<label htmlFor="password">Password</label>
<Input type="password" placeholder="Enter password" id="password" />
</InputGroup>
<Button type="submit" full="true">
Sign in
</Button>
</form>
<span>
Dont have an account?
<Link to="/signup"> Sign up</Link>
</span>
</EntryCard>
</EntryPage>
);
};
export default SignInPage;
how do i solve this error and pls🙏 what is a better way for this approach with custom hooks
Upvotes: 0
Views: 328
Reputation: 26226
Looking at these lines in particular:
const SignInPage = () => {
const { togglePassVisibility } = useToggle();
const toggle = togglePassVisibility(); // this calls dispatch every render!
return ( /* ... render ... */ );
}
Every time your component is rendered, you immediately call togglePassVisibility()
which will cause a new render. This is an infinite loop.
If you instead want to be able to call togglePassVisibility
as if it were called toggle
, you can do one of the following:
toggle
:const toggle = togglePassVisibility; // <-- no parentheses
const { togglePassVisibility: toggle } = useToggle();
// in hooks file
const useToggle = () => {
/* ... */
return [ togglePassVisibility ];
};
// in component
const [ toggle ] = useToggle();
Note: Don't forget to bind toggle to a button.
Upvotes: 3