Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typing mapStateToProps React Redux

I am not able to type the "state" parameter of a mapStateToProps

If I just change state : any instead of state: AppState it works and no error. But I would like to have a correct typing for my state parameter.

For now, I have this error on the mapStateToProps param of the connect()

No overload matches this call. The last overload gave the following error. Argument of type '(state: { quiz: IQuizInitialState; }) => StateProps' is no assignable to parameter of type 'MapStateToPropsParam'. Cannot assign the type '(state: { quiz: IQuizInitialState; }) => StateProps' to type 'MapStateToPropsFactory'. Parameters 'state' and 'initialState' are not compatible. Property 'quiz' is missing in type '{}' but required in type '{ quiz: IQuizInitialState; }'.ts(2769)

interface OwnProps {

}
interface StateProps {

}
interface DispatchProps {

}

type Props = OwnProps & StateProps & DispatchProps;


export class App extends Component<Props> {

  render() {
    return (
     <div>Hey</div>
    );
  }
}

const mapStateToProps = (state: AppState): StateProps => ({ 
})

const mapDispatchToProps = (dispatch: ThunkDispatch<{}, {}, AnyAction>): DispatchProps => {
    return {
    }
}


// The args 'mapStateToProps' generate the error
export default connect<StateProps,DispatchProps,OwnProps>(mapStateToProps, mapDispatchToProps)(App)

This is my rootReducer :

import { combineReducers } from 'redux';
import { QuizReducer } from './quiz';

const rootReducer = combineReducers({
    quiz: QuizReducer
});

export type AppState = ReturnType<typeof rootReducer>


export default rootReducer;

And the single reducer is :

import { TYPES } from '../actions/action-types';
import { IQuizListItem, Action } from '../models/index';
import { AnyAction } from 'redux';


export interface IQuizInitialState {
    quizListItem: IQuizListItem[]
}
const quizInitialState: IQuizInitialState = {
    quizListItem: []
}
export const QuizReducer = (state = quizInitialState, action: AnyAction): IQuizInitialState => {
    switch (action.type) {
        case TYPES.getQuizListItems:
            return {
                ...state,
                quizListItem: (action as Action<IQuizListItem[]>).payload
            }

        default:
            return state
    }
}

Thank you by advance guys !

like image 486
Topsy Avatar asked Oct 19 '19 20:10

Topsy


People also ask

What is mapStateToProps in React Redux?

As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.

How do you write reducers in Redux?

Let us see below how to write its reducer. const initialState = { isLoading: false, items: [] }; const reducer = (state = initialState, action) => { switch (action. type) { case 'ITEMS_REQUEST': return Object. assign({}, state, { isLoading: action.

What is mapStateToProps and mapDispatchToProps in React Redux?

The mapStateToProps and mapDispatchToProps deals with your Redux store's state and dispatch , respectively. state and dispatch will be supplied to your mapStateToProps or mapDispatchToProps functions as the first argument.

Can we use Redux with TypeScript?

We strongly recommend using TypeScript in Redux applications. However, like all tools, TypeScript has tradeoffs. It adds complexity in terms of writing additional code, understanding TS syntax, and building the application.


1 Answers

The type of your state is the same type you use for the whole state. since mapStateToProps takes the whole state to pass it down to selectors. in your case I believe this would be the correct type IQuizInitialState.

const mapStateToProps = (state: IQuizInitialState): StateProps => ({ 

})

EDIT

In your comment you mention IQuizInitialState isnt your whole application state. Then that one is not the one you need. You need a type for the whole application state. To achieve that you could create an interface for every single reducer type meaning your IQuizInitialState but for the other reducers into a single interface.

Ill have to asume here since I dont have your code base but consider

combineReducers({potato: quizReducer, tomato: otherReduzer})

you'll need a type

interface IApplicationState {
potato: IQuizInitialState;
tomato: IOTherInterfaceYouDefinedForThisReducer;
}

your combineReducers will probable look like :

combineReducers<IApplicationState>({
  potato: quizReducer,
  tomato: otherReduzer
});

I hope you get the idea.

EDIT 2 After reading your last comment I noticed you are asking for the mapStateToProps with two arguments. and you are just defining one. Your connect generics seems wrong then. you should consider the following:

connect<StateProps, DispatchProps, Props, IApplicationState>

where:

  • StateProps : describes what was returned by mapStateToProps()
  • DispatchProps: describes what is returned by dispatchToProps()
  • Props: Your component props
  • IApplicationState: Represents your Apps Redux whole state
like image 200
jstuartmilne Avatar answered Nov 04 '22 00:11

jstuartmilne