web-dev-qa-db-ja.com

Flowがdocument.getElementById(...)でReactDOM.renderを呼び出せない理由

フロータイプチェックでこのエラーが発生していました。

_Cannot call ReactDOM.render with document.getElementById(...) bound to container because null [1] is
incompatible with Element [2].

     src/index.js
      26│       </Switch>
      27│     </ScrollToTop>
      28│   </BrowserRouter>
      29│ </Provider>, document.getElementById("root"));
      30│

     /private/tmp/flow/flowlib_174a8121/dom.js
 [1] 646│   getElementById(elementId: string): HTMLElement | null;

     /private/tmp/flow/flowlib_174a8121/react-dom.js
 [2]  18│     container: Element,
_

コードは次のとおりです。

_// @flow
"use strict";
import React from "react";
import ReactDOM from "react-dom";
import {createStore, applyMiddleware} from "redux";
import {Provider} from "react-redux";
import {BrowserRouter, Switch, Route} from "react-router-dom";
import Home from "./components/home";
import Detail from "./components/detail";
import LevelOfGame from "./components/level-of-game";
import NotFound from "./components/not-found";
import ScrollToTop from "./components/scroll-to-top";

import reducers from "./reducers";

const createStoreWithMiddleware = applyMiddleware()(createStore);

ReactDOM.render(<Provider store={createStoreWithMiddleware(reducers)}>
  <BrowserRouter>
    <ScrollToTop>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/detail/:detailId" component={Detail}/>
        <Route path="/level-of-game" component={LevelOfGame}/>
        <Route path="*" component={NotFound} status={404}/>
      </Switch>
    </ScrollToTop>
  </BrowserRouter>
</Provider>, document.getElementById("root"));
_

getElementByIdで何らかの形でタイプを指定しなければならなかったと思います。

そこで、タイプ仕様の定数変数にdocument.getElementById("root");を格納することでエラーを修正しました。

_const root: any = document.getElementById("root");
_

エラーは修正されており、これが他の人々にとって役立つことを願っていますが、このエラーの原因を理解したいと思います。誰もがこれが何であるかを教えてくれますか?

14
sflow

Aleksey L。 コメントで最初にこれを取得しました。視覚的なスキャンを容易にするために、この情報を回答レベルまで上げたいと思いました。

フローは、document.getElementById("root");呼び出しがnullを返す可能性があることを通知します。この場合、アプリは完全にクラッシュします。それでは、それに対して警戒しましょう:

const root = document.getElementById('root')

if (root !== null) {
  ReactDOM.render(<App /> , root)
}

確かに、レンダリングするHTMLを制御する可能性が高いことを考えると、これは少し面倒です。

20
cogell

Cogellの答えは正しいですが、コードをよりシンプルにし、例外を追加することをお勧めします。

_ReactDOM.render(
 <Provider store={createStoreWithMiddleware(reducers)}>
  <BrowserRouter>
    <ScrollToTop>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/detail/:detailId" component={Detail}/>
        <Route path="/level-of-game" component={LevelOfGame}/>
        <Route path="*" component={NotFound} status={404}/>
      </Switch>
    </ScrollToTop>
  </BrowserRouter>
 </Provider>, // $FlowIgnore
 document.getElementById("root")
);
_

「$ FlowIgnore」コメントに注意してください

そして、_.flowconfig_ファイルで、これを「オプション」フィールドに追加します。

suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore

3
Craig O'Connor