Connecting the home page

Let's connect the home page to the store:

  1. In HomePage.tsx, let's add the following import statements:
import { connect } from 'react-redux';
import { ThunkDispatch } from 'redux-thunk';
import { AnyAction } from 'redux';

We've imported a function called connect from React Redux that will allow us to connect the HomePage component to the store. We've also imported some useful TypeScript types from Redux and Redux Thunk. 

  1. We are going to use the Redux store for the unanswered questions, so let's import the action creator that will get these, along with the type for the store's state:
import {
getUnansweredQuestionsActionCreator,
AppState
} from './Store';
  1. Let's remove the getUnansweredQuestions function from the import statement from QuestionsData.ts. We will eventually get this data from the Redux store. This should leave this import statement as follows:
import { QuestionData } from './QuestionsData';

  1. The state in the Redux store, as well as the dispatched action creator, is going to be accessible from the HomePage component via props. So, let's create a props interface for what we expect:
interface Props extends RouteComponentProps {
getUnansweredQuestions: () => Promise<void>;
questions: QuestionData[] | null;
questionsLoading: boolean;
}

The interface extends the RouteComponentProps type because this is the current props type. We have added three props for getting and storing the unanswered questions, as well as for whether they are in the process of being loaded.

  1. Now, we can use this interface in the HomePage component and destructure the props:
export const HomePage: FC<Props> = ({
history,
questions,
questionsLoading,
getUnansweredQuestions
}) => { ... }
  1. We no longer need the questions and questionsLoading states, so let's remove the useState statement inside the component. We need to remember to remove useState from the React import statement as well. In addition, the doGetUnansweredQuestions function is also redundant, so let's remove this as well.
  2. The first statement in the component is now the useEffect statement, which gets the unanswered questions when the component is mounted. We need to change this to call the action creator in our Redux store to get the questions:
useEffect(() => {
if (questions === null) {
getUnansweredQuestions();
}
}, [questions, getUnansweredQuestions]);

So, if the questions state in the Redux store is null, we start the process of getting the unanswered questions.

Notice that we include the questions and getUnansweredQuestions functions as dependencies for the useEffect function so that it is executed if these ever change.

  1. We still need to connect the component to the store. We do this using the connect function we imported earlier into a default export statement at the bottom of HomePage.tsx:
export default connect(
mapStateToProps,
mapDispatchToProps
)(HomePage);

This connects the component to our store, which is provided to us by the Provider component, which is higher up in the component tree. The connect function also invokes two mapper functions, mapStateToProps and mapDispatchToProps, which map the state and action creators from the store into the component props that we'll implement later.

  1. Now that we have a default export for the HomePage component, let's remove its named export. So, the HomePage component should now be defined as follows, without the export keyword:
const HomePage: FC<Props> = ...
  1. Let's define the mapStateToProps function above the default export statement:
const mapStateToProps = (store: AppState) => {
return {
questions: store.questions.unanswered,
questionsLoading: store.questions.loading
};
};

This function takes in the store state and returns the questions and questionLoaded props that are required by our component. So, it maps state from the store into the component props, as the name suggests.

  1. Let's define the mapDispatchToProps function just beneath the mapStateToProps function:
const mapDispatchToProps = (
dispatch: ThunkDispatch<any, any, AnyAction>,
) => {
return {
getUnansweredQuestions: () =>
dispatch(getUnansweredQuestionsActionCreator()),
};
};

This dispatches and maps the action creator to get unanswered questions into the component props.

Notice that the TypeScript type for the dispatch parameter is ThunkDispatch. This is a type from the Redux Thunk library that takes in three parameters for the asynchronous function result type, asynchronous function parameter type, and the last action created type, respectively. Although we are dispatching only one action creator in this case, we could be dispatching different action creators, which is why we pass in the any type and the AnyAction type in the generic parameters.

  1. Let's move on to the App.tsx file and change the import statement for HomePage, so that it uses the default export:
import HomePage from './HomePage';
  1. If the app isn't running, type npm start in the Terminal to start it. The app will run fine and the unanswered questions will be rendered on the home page, just as they were before we added the Redux store. 

Congratulations—we have just connected our first component to a Redux store!

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

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