概要
表題のエラーについて、Reactをやったことある人であれば、一度は見かけたことがある内容かもしれません。私はいまだに、このReactのエラー仕様をド忘れしてハマることがあるので、今回は備忘でメモ書きします。
どういう時に発生するのか
こちらのteratailの記事にある通り、「useXxx関数を条件やループに入れたり、手前でreturnしてしまったりするとこういうエラー」となります。NGパターンの詳細については、Rendered more hooks than during the previous render (React)の記事でも解説されています。
例えば以下のようなソースでは、useEffectの手前で条件式でreturnしてしまってるので、エラーになります。
import { useContext, useEffect } from "react";
import { useQuery } from "react-query";
import { SampleContext } from "../context/SampleProvider";
import { getSearchMaster } from "../service/api/SearchService";
export default function SampleComponent() {
const { master, setMaster } = useContext(SampleContext);
const { data, isError, isLoading } = useQuery("master", getSearchMaster);
if (isLoading) {
return (<>Loading・・・</>);
}
if (isError) {
return (<>Error</>);
}
useEffect(() => {
if (data) {
setMaster(data);
}
}, [data]);
return (<>成功</>);
}
対応
トップレベルにて、条件付きでuseXxxを呼び出したり、useXxxが呼ばれる前にreturnしないよう、修正すれば大丈夫です。
上記のサンプルソースについて、以下のように修正すればエラーは解消されます。
import { useContext, useEffect } from "react";
import { useQuery } from "react-query";
import { SampleContext } from "../context/SampleProvider";
import { getSearchMaster } from "../service/api/SearchService";
export default function SampleComponent() {
const { master, setMaster } = useContext(SampleContext);
const { data, isError, isLoading } = useQuery("master", getSearchMaster);
useEffect(() => {
if (data) {
setMaster(data);
}
}, [data]);
if (isLoading) {
return (<>Loading・・・</>);
}
if (isError) {
return (<>Error</>);
}
return (<>成功</>);
}