web-dev-qa-db-fra.com

Pourquoi Flow ne peut pas appeler ReactDOM.render avec document.getElementById (...)

J'obtenais cette erreur ci-dessous lors de la vérification du type de flux.

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,

Le code est ci-dessous.

// @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"));

Je crois que je devais spécifier le type en quelque sorte dans getElementById.

J'ai donc corrigé l'erreur en stockant document.getElementById("root"); dans une variable constante avec une spécification de type:

const root: any = document.getElementById("root");

L'erreur est corrigée et j'espère que cela est utile pour d'autres personnes, mais j'aimerais comprendre ce qui a causé cette erreur. Quelqu'un peut-il être si gentil de me dire ce que c'était?

14
sflow

Aleksey L. a obtenu ceci en premier dans les commentaires, je voulais amener ces informations au niveau de réponse pour un balayage visuel plus facile.

Flow vous informe que l'appel document.getElementById("root"); peut renvoyer null auquel cas l'application se bloquerait complètement. Alors gardons-nous contre cela:

const root = document.getElementById('root')

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

Certes, cela peut sembler un peu ennuyeux étant donné que, selon toute probabilité, vous contrôlerez le code HTML dans lequel vous effectuez le rendu.

20
cogell

Bien que la réponse de Cogell soit correcte, je dirais de garder le code plus simple et d'ajouter une exception.

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")
);

Remarquez le commentaire "$ FlowIgnore"

puis dans votre fichier .flowconfig ajoutez ceci au champ "options":

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

3
Craig O'Connor