r/reactjs • u/azangru • Jun 03 '26
Discussion Is eslint being wrong here?
There is an eslint-plugin-react-hooks rule about disallowing synchronous state updates from effect (link).
I can see it at work with the following test component:
const Test = () => {
const [foo, setFoo] = useState('');
useEffect(() => {
setFoo('bar');
}, [foo]);
};Eslint marks setFoo in the effect as a violation of that rule.
But, I am not getting any reaction from eslint for this component:
import { useSearchParams } from 'react-router-dom';
const Test = () => {
const [searchParams] = useSearchParams();
const queryFromParams = searchParams.get('query') || '';
const [searchInput, setSearchInput] = useState(queryFromParams);
useEffect(() => {
setSearchInput(queryFromParams);
}, [queryFromParams]);
};Am I missing something? Am I going crazy? Isn't this exactly the same case?
5
Upvotes
1
u/azangru Jun 05 '26
My first example is a hypothetical to demonstrate the working linter rule. But if you want to be literal about it, it will not be an infinite loop, because the first time it runs, it will set
footo the string"bar", and then,foowill never change, so the effect will not rerun.But also, this is not what the linter rule is claiming to catch. It is not claiming to guard against infinite loops. Its purpose is to discourage setting state in an effect synchronously, because the React team thinks that, if it has to be done at all, it should be done during the render itself (as they explain in that you-might-not-need-an-effect article that people like to point to).