In this lesson we are going to take a React and Redux application and add flow types throughout. This includes type checking a react component, a reducer, some actions, and a connect method.
Instructor: [00:00] Inside of this createReactApp, I've installed Redux, as well as Flow. Then also made this Flow script so that as we add our Flow types, we can run this script in our terminal, and make sure everything's working correctly.
[00:14] Inside of our app.js file, I have created this counter component, where if we look in the UI, it simply just adds and subtracts. Now, I've already gone through and integrated Redux. These two buttons, when clicked on, are firing Redux action creators. Then we're using our reducer state to show the current number.
[00:34] Both our state and Redux action creators are being used with the React Redux connect function, and then exported out. Inside of this index.js file, we've imported this counter component, and then defined our reducer.
[00:49] You can see that we have an initial state of zero, and have two methods that handle the increment and decrement of our state. Finally, we create our store, add our counter component, and connect it all up with ReactDOM.
[01:03] As soon as we add our Flow tag at the top of these pages, then save them out, grab our terminal, we can see instantly that Flow has found some errors with our code. Let's go ahead and work through these.
[01:21] We know that our counter component relies on three things, our reducer state, and these two Redux action creators. Let's first define these types, and then we can integrate them into our React component and Redux concepts.
[01:34] Up here at the top, let's do export type increment equals an object type increment. Then export type decrement equals an object type decrement. Then export type action is an increment or a decrement. Then export type state equals an object count as a number.
[01:56] With these action types defined, whenever they're used, whether it be as a prop inside of our counter component within the connect function or inside of our reducer, the type will be consistent throughout.
[02:10] Same goes for our general action and state types. As we reference state throughout the files, and within our components, it will be kept consistent throughout. Now, let's create our props type. We'll do decrement equals a function that returns a decrement action, and then increment, which is a function that returns an increment action, as well as our count as a number.
[02:34] Then we can pass this through as a type argument to our component. Now that we've type checked our component props, let's go ahead and type check our connect function. Inside of this actions object, we want to make sure that this increment property returns our increment action.
[02:50] We'll do that by adding the increment type, and then on the other side of the decrement, we'll do the same thing. Now, inside of our mapStateToProps, we want to make sure that we actually do return our state in the correct type format.
[03:04] We do that by adding parentheses around this, and making sure that we return our state type. Next, we're going to import our connector type, which we get from React Redux, and then use it on our const connector variable.
[03:24] Connector has two type arguments. We're going to do an object and props. This connector type does all the heavy type checking for us. The first type argument is for any owned props, and the second is for our component props type.
[03:40] Now that we've gone through and added types to our app.js page, let's save this out, check our terminal, and see how it's looking so far. It looks like we still have some errors and they are coming from the index page.
[03:54] Let's go and add types to our index page now. Inside of our index.js file, we want to import our increment, decrement action and state types that we've defined in our app file. Now, let's go and add our state type throughout this file.
[04:13] We'll add it to our initial state, our handleIncrement function, as well as the handleDecrement function, and set up of our reducer, and finish up with our create store variable. Next up, we'll add our action type to our reducer.
[04:30] Finally, we'll finish up by adding our individual increment and decrement types to our reducer methods. Perfect. To recap, we've defined our types inside of our app file here, and then we integrated them into our React component, and our connect method.
[04:50] Then inside of our index.js file, we've imported these types, and then added them to every instance our actions and state are referenced. This includes inside of our reducer and our store instance. Now, let's check our terminal, and see if there are any errors left.
[05:07] It looks like we still do have an error, and it deals with the element type inside of our ReactDOM method. Let's go ahead and fix that right now. Flow makes this error because it cannot find this element here.
[05:27] In order to fix this, we could rearrange our code between our other files, or we can go through our Flow config, and add an ignore option. Now, with this suppress comment option that we've got here, we can add this commented out Flow ignore to our index file. It will ignore the next line.
[05:49] If we save that and open up our terminal again, run our Flow script. As it parses the new logs, we can see if we've covered all of our errors, and it looks like we have.
Why not to use the integrated Flow extension in VSCode? Definitely much better than checking the errors in the console...
Hey Flavio, I decided to be agnostic towards editors and use a more universal way to check for Flow errors.
This is all nice with a small test app, but with a lot of actions of different types, having to refer to types with string literals instead on constants is tedious and error prone. Is there a way to do flow typing and referring back to constants? I have not been able to do that and now I am stuck between able to use constants or flow type. I want to have them both :)