😺
【MUI】useEffectで非同期処理を実行しTextFieldの初期値を設定する
概要
useEffect()で非同期処理を実行し、取得した値を TextField の初期値として表示する機会があった
実装した見たところ、useEffect()で取得した値がフォームに表示されなかったので原因と対処法をメモ
完成イメージ
環境
React 18
MUI 5
詳細
当初の失敗コードが以下
NG
const [data, setData] = useState<response>({
uri: "",
});
useEffect(() => {
(async () => {
const apiResponse = await apiRequest();
setData(apiResponse);
})();
}, []);
return (
<>
<TextField defaultValue={data.uri} disabled fullWidth />
</>
);
これでは取得した値がフォームに表示されなかった
原因
- useState で値を管理する場合は制御コンポーネントとして扱う
- defaultValue は非制御コンポーネントで扱う場合の初期値指定方法
- 制御コンポーネントとして扱う場合は value で OK
OK
const [data, setData] = useState<response>({
uri: "",
});
useEffect(() => {
(async () => {
const apiResponse = await apiRequest();
setData(apiResponse);
})();
}, []);
return (
<>
<TextField value={data.uri} disabled fullWidth />
</>
);
defaultValue を value にしたところ成功した
参考
controlled component(制御されたコンポーネント)は、入力値などを state で管理するようにように制御されたコンポーネントです。
Controlled component のサンプルです。
React.useState で input 要素の入力値を管理します。
you don't need to update its default value in useEffect(). and use value instead of defaultValue, just do it like this:
const Editform = () => {
const [uname, setname] = useState("Jubed Alam");
return (
<form>
<TextField
margin="normal"
label="Name"
fullWidth
name="name"
value={uname}
onChange={(e) => setname(e.target.value)}
/>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</form>
);
};
Discussion