When I try to set a state by using an onClick I get an infinite loop.
My component
'use client'
import { use, useState } from "react";
import { gql } from "@apollo/client";
import client from "/apollo-client";
import { localesQuery } from '/graphql/queries';
// Import Components
import { LanguageIcon } from '@heroicons/react/24/solid'
import Image from 'next/image';
export default function LanguageSwitcher({className}) {
const locales = use(getLocales())
const [dropdownCollapsed, setDropdownCollapsed] = useState(false);
return (
<button className={className} onClick={() => setDropdownCollapsed(!dropdownCollapsed)}>
<LanguageIcon className="h-5 w-5 text-dark dark:text-white"/>
<div className="dropdown-list absolute right-0 -bottom-4 transform translate-y-full transition-colors duration-150 border border-gray-200 dark:border-gray-800 bg-white dark:bg-black md:bg-opacity-70 rounded-2xl overflow-hidden ">
<ul className="w-40 flex flex-col">
{locales.map((locale, index) => (
<li key={index}>
<a className="flex items-center px-4 py-3 hover:bg-gray-100 dark:hover:bg-zinc-900 w-full">
<Image height="20" width="24" className="rounded mr-1.5" src={`images/${locale.attributes.code}.svg`} alt={`${locale.attributes.name} flag`} />
<span>{locale.attributes.name}</span>
</a>
</li>
))}
</ul>
</div>
</button>
)
}
async function getLocales() {
const { data } = await client.query({
query: localesQuery,
});
return data.i18NLocales.data;
}
I tried adding an arrow function in between, but this only fixes it until I click the button, because then it renders again and starts the recursion.
Simplified version of my component:
import { useState } from "react";
export default function Component() {
const [variable, setVariable] = useState(false);
return (
<button onClick={() => setVariable(!variable)}>Click me!</button>
)
}
So my question is how do I setVariable
with an onClick
. I'd assume this was the right approach but maybe I am doing something wrong.
The way I fixed is to separate the fetching of data in to a child component. After reading this I learned that one should prevent fetching data and using hooks in the same component.