0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【React/laravel】axiosによる非同期のAPI callの結果を待ってからStateに値を入れたかった【小説印刷支援サイト】

Last updated at Posted at 2020-04-26

承前

小説を簡単に同人誌の形にできる印刷できるWebサイトを作りたいと思っている。
今回はその前段階として、印刷する際のプレビュー画面を作成していたときに躓いた話。

事象

直前まで動いていたReactコンポーネントが急にエラーを吐き始めた。

Uncaught TypeError: Cannot read property 'chapterNumber' of undefined
    at RenderUi (index.js:70616)
    at renderWithHooks (index.js:48209)
    at mountIndeterminateComponent (index.js:50888)
    at beginWork (index.js:52002)
    at HTMLUnknownElement.callCallback (index.js:33594)
    at Object.invokeGuardedCallbackDev (index.js:33643)
    at invokeGuardedCallback (index.js:33698)
    at beginWork$1 (index.js:56609)
    at performUnitOfWork (index.js:55560)
    at workLoopSync (index.js:55536)

chapterNumberChapterContentのメンバ。
ChapterContentNovelWithContentsのメンバ。

調査

ChapterContentのインスタンスが空だった。
なんならNovelWithContentsのインスタンスも空だった。
('、3_ヽ)_

やりたかったことと原因

やりたかったこと

NovelWithContentsがなぜ空なのか

axiosで取得したJSONモデルデータが詰まっている予定だったが、ログを出してみたら問題が分かった。

  • componentDidMount()はComponent描画後に呼ばれるため、Component描画時にココで取得する予定の値を参照してしまうとエラーになる。

その後、もう一つの問題も分かった。

  • axiosは非同期処理をするので、Constructorなどで事前に値を取得しようとしてもデータ取得処理が間に合うかどうか分からない(間に合わない)

    componentDidMount() {
        console.log(this.state.novelId+"sssssssssssssssssssssssss");
        axios
            .get(/*API CALL*/)
            .then(response => {
                let data: NovelWithContents = response.data;
                console.log(response.data);
                this.setState({ contentsJson: data });
            })
            .catch(() => {
                console.log("通信に失敗しました。")

            });
    }

結論

前処理の部分で、データが無いクラスのプロパティを参照してエラーを吐いていた。

対処

失敗した方法

constructorstate初期化後にaxios以下を移してもうまく行かなかった。
renderに移しても同様。

うまく行った方法

色々やった。

  • 前処理後の値をStateにして初期値を与えた。
    • 初回のRender時、即ちaxiosが間に合ってない時に空でエラーを吐かなくなった。
  • 初期化処理をaxiosのfinally()処理に集めた。
    • これによりデータ取得と初期化処理の順番の整合性を取りながら、非同期処理という体は崩さずに済んだ。
  • 上記を可能にするために全体的にリファクタリング

    componentDidMount() {
        axios
            .get(/*API CALL*/)
            .then(response => {
                let data: NovelWithContents = response.data;
                console.log(response.data);
                this.setState({ contentsJson: data });
            })
            .catch(() => {
                console.log("通信に失敗しました。")

            }).finally(()=>{
                let hoge="";
                //前処理。
                });

    }

結局3時間くらいハマってしまった。

反省

  • Reactへの理解度が浅い中で始めたProjectだったので、設計はあとでキチンとやりなおす。

今回実現した機能

小説のページング

小説印刷支援サイト

やや遅れ気味。7月リリースを目指したい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?