はじめに
リダイレクト後に更新後のstateを表示させることについて、詰まったので簡単にまとめてみます
やりたいこと
データを削除した後に同じ画面にリダイレクトさせたい。その際、画面に表示されるデータは削除後の内容にしたい
前提
リダイレクトさせてもDOMの更新がされないため、画面には削除前のデータが表示されている状況でした
方法
はじめにuseEffectを使い、強制的にレンダリングさせる方法を考えましたが、これはパフォーマンスやデバッグの観点からreact的に非推奨のようでした。
次にuseRecoilでstateをグローバルに管理する方法も考えましたが、修正する影響範囲が多かったことから一旦はコンポーネント間でpropsの受け渡しをしてstateを更新させる方法を選択しました
ファイル(一部)
components/pages/MyData.tsx(親)
略
const [datas, setDatas] = useState<Data[]>();
const getDatas = async () => {
const res = await axios.get(`${apiURL}/data`).then(function (res) {
setDatas(res.data.datas);
});
}
useEffect(() => {
getDatas();
}, []);
略
- <DataCards pageSize={6} datas={datas} my={true} />
+ <DataCards pageSize={6} datas={datas} my={true} refreshData={getDatas} />
components/molecules/Cards.tsx(子)
type Props = {
datas: Data[];
my?: boolean;
+ refreshData?: () => void;
};
export const Datas = memo((props: Props) => {
略
+ const refreshDatas = () => {
+ if (props.refreshData !== undefined) {
+ props.refreshData()
+ }
+ }
const navigate = useNavigate();
return (
<>
{my ? (
- <MyDataCard card={item} />
+ <MyDataCard card={item} datas={refreshDatas} />
) : (
<DataCard card={item} />
);
});
components/molecules/MyDataCard.tsx(孫)
type Props = {
card: Card;
+ datas: () => void;
};
export const MyDataCard = memo((props: Props) => {
const deleteData = (id: string) => {
setIsOpen(false)
axios
.delete(`${apiURL}/data/${id}`)
.then((res: AxiosResponse<Data>) => {
if (res.status === 200) {
- navigation("/");
console.log("削除しました");
toaster('削除しました', 'success');
+ props.datas()
} else {
console.log("失敗しました");
toaster('失敗しました', 'warning');
}
})
.catch(() => {
toaster('システムエラーです', 'error');
console.log("catch");
});
}
略
}
コンポーネントの関係
- 親コンポーネント(MyData.tsx)
- 子コンポーネント(DataCards.tsx)
- 孫コンポーネント(MyDataCard.tsx)
処理の概要
①孫コンポーネントで削除ボタンをクリックするとデータを削除する関数を実行
- 孫コンポーネントでonclickイベントにdeleteData関数を指定しています
②データを取得する関数を親から子を経由して受け取り、実行
- 今回は子コンポーネントを経由する必要があるので、親と子、子と孫間でそれぞれpropsの受け渡しを定義しています
- 最終的にdeleteData関数内で親コンポーネントで定義したgetDatas関数を実行しています
③親のstateが更新され、画面のレンダリングが走る
親コンポーネントで定義したgetDatas関数が孫コンポーネントで呼び出されると、関数内のsetDatasでstateが更新されます。
これによって孫コンポーネントでの変更が親コンポーネントに伝わり、レンダリングが走ります
おわりに
今後はuseRecoilも挑戦していきたいです。