UseEffectで取得したデータをUseContextで共有する
useContextの記事を色々漁ってもハードコーディングした値をProviderやcreateContextに渡すような非現実的な例ばかりだったので備忘録。
アプリ起動時にuseEffectでデータを取得し、そのデータをコンテクストとしてアプリ内で共有したい場合を想定。
他にも方法はあるのかもしれないが、とりあえず動いた方法をメモ。
App.jsx
import { useState, useEffect, createContext } from "react";
import axios from "axios";
export const DataContext = createContext(); //コンテクストオブジェクト準備
export default function App() {
const [data, setData] = useState({}); //useContextに渡すデータ用のStateを用意
useEffect(() => {
async function fetchData(){
try {
const response = await axios.get(URL,{
headers: {
"Content-Type": CONTENT_TYPE,
"x-api-key": X_API_KEY
}
});
setData(response.data); //Stateをレスポンスで更新
} catch (e) {
//エラー処理
}
};
fetchData();
}, [])
return (
<DataContext.Provider value={data}>
//...Routerなどのコンポーネント
</DataContext.Provider>
)
}
HomePage.jsx
import { useContext } from "react";
export default function HomePage() {
const data = useContext(DataContext); //コンテクストのデータ取得
//...その他の処理
}
useStateを使わずに変数(const dataなど)やuseRefにレスポンスを渡し、コンテクストのvalueにしようとするとHomePage.jsxのdataは空オブジェクトになる。
useEffectはレンダリング後に実行される関数なので、レスポンスが取得されたタイミングで再レンダリングをさせないとコンテクストのvalueが新しいものではなく、初期値の空データになってしまう。したがって再レンダリングを発生させるためにuseStateによるState管理を利用する。