kanfutrooper
@kanfutrooper (masaomi)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

エラー表示『TS2588: Cannot assign to 'isSubmitting' because it is a constant.』を改善したいです。

解決したいこと

React(Typescript)で掲示板のようなWebアプリをつくっています。
記事を投稿する機能の実装中に下記のエラーが発生しました。
解決方法を教えて下さい。

発生している問題・エラー

TS2588: Cannot assign to 'isSubmitting' because it is a constant.
    28 |   const onSubmit = async (data: { title: string; content: string }) => {
    29 |     await createTodoApi(data).catch((e) => {
  > 30 |       isSubmitting = false;
       |       ^^^^^^^^^^^^
    31 |     });
    32 |     reset();
    33 |   };

自分で試したこと

下記のコードを入力したが、改善しなかった。

その①

let isSubmitting = false; 

その②

import { useState } from 'react';

const [isSubmitting, setIsSubmitting] = useState(false);

setIsSubmitting(false);

該当するソースコード

AddTodo.tsx
//その②
//import { useState } from 'react';

import { useForm } from 'react-hook-form';
import {
  Box,
  Button,
  FormControl,
  FormErrorMessage,
  Textarea,
} from '@chakra-ui/react';
import { createTodoApi } from '../../../stores/slices/todoAPI';

type FormValues = {
  title: string;
  content: string;
};

// その①
// let isSubmitting = false;

const AddTodo: React.FC = () => {
//その②
//const [isSubmitting, setIsSubmitting] = useState(false);

  const {
    handleSubmit,
    register,
    formState: { errors, isSubmitting },
    reset,
  } = useForm<FormValues>();
  
 const onSubmit = async (data: { title: string; content: string }) => {
    await createTodoApi(data).catch((e) => {
      isSubmitting = false;
//その②
//setIsSubmitting(false);
    });
    reset();
  };

  return (
    <Box display='flex' justifyContent='center'>
      <form onSubmit={handleSubmit(onSubmit)}>
        <FormControl
          isInvalid={!!errors.title}
          w={{ base: '90vw', sm: '80vw', md: '70vw', lg: '60vw' }}
        >
          <Textarea
            id='title'
            color='black'
            placeholder='Enter Title'
            _placeholder={{ color: 'inherit' }}
            {...register('title', { required: 'Please enter title.' })}
          />

          <FormErrorMessage>
            {errors.title && errors.title.message}
          </FormErrorMessage>
        </FormControl>
        <FormControl
          isInvalid={!!errors.content}
          w={{ base: '90vw', sm: '80vw', md: '70vw', lg: '60vw' }}
        >
          <Textarea
            id='content'
            color='black'
            placeholder='Enter Content'
            _placeholder={{ color: 'inherit' }}
            {...register('content', { required: 'Please enter content.' })}
          />
          <FormErrorMessage>
            {errors.content && errors.content.message}
          </FormErrorMessage>
        </FormControl>
        <Box w='100%' display='flex' justifyContent='flex-end'>
          <Button
            mt={4}
            colorScheme='whatsapp'
            isLoading={isSubmitting}
            type='submit'
            variant='outline'
          >
            Submit
          </Button>
        </Box>
      </form>
    </Box>
  );
};

export default AddTodo;

0

2Answer

質問のタイトルはエラー内容がわかりやすい要約を書いてください,

本題ですが,コンポーネント内でisSubmittingconst定義されているので,このスコープは上書きされることはありません.
そもそもの話isSubmittingstateのような動きをするはずなので直接変更自体まずいことです.

1Like

Comments

  1. @kanfutrooper

    Questioner

    @Vercleneさん、質問のタイトルの件、ご指摘ありがとうございます!
    早速、改善しました。

isSubmitting は、 onSubmit の async 関数が呼び出された瞬間に true になり、 その関数の実行が終了したときに false になる

というのがデフォルトの挙動だと記憶していますが、「react-hook-form に任せて、自分では何もコードを追加しない」が正解だと思いますが、試してみましたか?

  const {
    handleSubmit,
    register,
    formState: { errors, isSubmitting },
    reset,
  } = useForm<FormValues>();

  const onSubmit = async (data: { title: string; content: string }) => {
    await createTodoApi(data);
    reset();
  };
1Like

Comments

  1. もしかしたら react-hook-form の handleSubmit は Promise の失敗に対応していないのか...?
    react-hook-form の公式ドキュメントが説明不足でわかりにくいですが、とにかく下のように書けば createTodoApi が原因であるかどうか確認できると思うので、そこからエラー原因を辿っていけると思います。

    try {
      await createTodoApi(data);
      reset();
    } catch (e: unknown) {
      console.error(e);
    }
    
  2. あ、見落としてました。やっぱり上記の通り catch しないとダメですね

    handleSubmit function will not swallow errors that occurred inside your onSubmit callback, so we recommend you to try and catch inside async request and handle those errors gracefully for your customers.

    const onSubmit = async () => {
      // async request which may result error
      try {
        // await fetch()
      } catch (e) {
        // handle your error
      }
    };
    
    <form onSubmit={handleSubmit(onSubmit)} />
    
  3. @kanfutrooper

    Questioner

    Honey 32さん、いつも丁寧な解説付きのアドバイス、ありがとうございます!
    色々思考錯誤して、下記のコードを書き換えて、何とか上記のエラーを解消しました。
    丁寧な解説付きのアドバイス、本当にありがとうございました!

    import { useState } from 'react';
    const [isSubmitting, setIsSubmitting] = useState(false);
    //formState: { errors, isSubmitting },
    setIsSubmitting(false);
    

Your answer might help someone💌