😺

【MUI】useEffectで非同期処理を実行しTextFieldの初期値を設定する

2023/07/12に公開

概要

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 にしたところ成功した

参考

https://zenn.dev/longbridge/articles/640710005e11b1

controlled component(制御されたコンポーネント)は、入力値などを state で管理するようにように制御されたコンポーネントです。
Controlled component のサンプルです。
React.useState で input 要素の入力値を管理します。

https://stackoverflow.com/questions/69294847/issue-in-textfield-default-value-set-using-the-useeffect-hook-in-the-material-ui

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>
  );
};
GitHubで編集を提案

Discussion