Installing and initializing Flow

Before you can start implementing type-safe React components, you need to install and initialize Flow. I'll show you how this is done with a create-react-app environment, but the same steps can be followed for almost any React environment.

You can install Flow globally, but I would recommend installing it locally, along with all the other packages that your project depends on. Unless there's a good reason to install something globally, install it locally. This way, anyone installing your application can get every dependency by running npm install.

To install Flow locally, run the following command:

npm install flow-bin --save-dev

This will install the Flow executable locally to your project and will update your package.json so that Flow is installed as a dependency of your project. Now let's add a new command to package.json so that you can run the Flow type checker against your source code. Make the scripts section look like this:

"scripts": { 
  "start": "react-scripts start",
  "build": "react-scripts build", 
  "test": "react-scripts test --env=jsdom", 
  "eject": "react-scripts eject", 
  "flow": "flow" 
}, 

Now you can run Flow by executing the following command in your Terminal:

npm run flow

This will run the flow script as expected, but Flow will complain about not being able to find a Flow configuration file:

Could not find a .flowconfig in . or any of its parent directories. 

The easiest way to resolve this issue is to use the flow init command:

npm run flow init 

This will create a .flowconfig file in your project directory. You don't need to worry about changing anything in this file right now; it's just that Flow expects it to be present. Now when you run npm run flow, you should get a message that indicates there are no errors:

Launching Flow server for 05/installing-and-initializing-flow
Spawned flow server (pid=46516)
No errors!  

It turns out that none of your source files were actually checked. This is because by default, Flow only checks files that have the // @flow directive as their first line. Let's go ahead and add this line at the top of App.js:

// @flow 
import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import './App.css'; 
 
class App extends Component { 
  render() { 
    return ( 
      <div className="App"> 
        <header className="App-header"> 
          <img src={logo} className="App-logo" alt="logo" /> 
          <h1 className="App-title">Welcome to React</h1> 
        </header> 
        <p className="App-intro"> 
          To get started... 
        </p> 
      </div> 
    ); 
  } 
} 
 
export default App; 

Now that Flow is checking this module, we're getting an error:

      6: class App extends Component {
                           ^^^^^^^^^ Component. Too few type arguments. Expected at least 1

What does this mean? Flow attempts to provide an explanation on the next line of the error output:

Component<Props, State = void> { 
          ^^^^^^^^^^^^ See type parameters of definition here. 

Flow is complaining about the Component class that you're extending with App. This means that you need to provide at least one type argument to Component for props. Since App isn't actually using any props, this could just be an empty type for now:

// @flow 
import React, { Component } from 'react'; 
import logo from './logo.svg'; 
import './App.css'; 
 
type Props = {}; 
 
class App extends Component<Props> { 
  render() { 
    return ( 
      <div className="App"> 
        <header className="App-header"> 
          <img src={logo} className="App-logo" alt="logo" /> 
          <h1 className="App-title">Welcome to React</h1> 
        </header> 
        <p className="App-intro"> 
          To get started... 
        </p> 
      </div> 
    ); 
  } 
}
export default App;

Now when you run Flow again, there aren't any errors in App.js! This means that you've successfully annotated your module with type information that Flow used to statically analyze your source to make sure everything is sound.

So how did Flow know what the Component class from React was expecting in terms of its generics? It turns out that React is itself Flow type-annotated, and this is how you get specific error messages when Flow detects a problem.

Next, let's add the // @flow directive to the top of index.js:

// @flow 
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import './index.css'; 
import App from './App'; 
import registerServiceWorker from './registerServiceWorker'; 
 
const root = document.getElementById('root'); 
 
ReactDOM.render( 
  <App />, 
  root 
); 
 
registerServiceWorker(); 

If you run npm run flow again, you'll see the following error:

    Error: src/index.js:12
     12:   root
           ^^^^ null. This type is incompatible with the expected param 
                type of Element  

This is because the value of root comes from document.getElementById('root'). Since there's no DOM for this method to return an element, Flow detects a null value and complains. Since this is a legitimate concern (the root element might not be there) and we need path for Flow to follow when there's no element, you can add some logic to handle this case:

// @flow 
import React from 'react'; 
import ReactDOM from 'react-dom'; 
import './index.css'; 
import App from './App';
import registerServiceWorker from './registerServiceWorker'; const root = document.getElementById('root');
if (!(root instanceof Element)) { throw 'Invalid root'; } ReactDOM.render( <App />, root ); registerServiceWorker();

Before calling ReactDOM.render(), you can manually check the type of root to make sure that it's what Flow expects to see. Now when you run npm run flow, there are no errors.

You're all set! You have Flow installed and configured locally, and you have the initial source from create-react-app passing the type check. You can now proceed to develop type-safe React components.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.161.77