I am getting an error trying to type the parameters for my react component. I would like to stronly type what properties will be on the props and state of a component, but when I do so using Redux, I am getting an error when I pass mapStateToProps to the connect function.
This is the component code:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import FileExplorer from '../components/file-explorer/file-explorer';
import { ISideMenu, ISideMenuState } from '../models/interfaces/side-menu';
class SideMenu extends Component<ISideMenu, ISideMenuState> {
render() {
return (
<div>
{this.props.fileExplorerInfo !== null &&
<FileExplorer fileExplorerDirectory={this.props.fileExplorerInfo.fileExplorerDirectory}/>
}
</div>
);
}
}
const mapStateToProps = (state: ISideMenuState) => {
return {
fileExplorerInfo: state.fileExplorer
};
};
export default connect<ISideMenu, null, ISideMenuState>(mapStateToProps)(SideMenu);
So the error occurs on this line:
export default connect<ISideMenu, null, ISideMenuState>(mapStateToProps)(SideMenu);
and when I hover over the word "mapStateToProps" in that line I am seeing the error:
Argument of type '(state: ISideMenuState) => { fileExplorerInfo: FileDirectoryTree | null; }'
is not assignable to parameter of type 'MapStateToPropsParam<ISideMenu, ISideMenuState, {}>'.
Type '(state: ISideMenuState) => { fileExplorerInfo: FileDirectoryTree | null; }' is not
assignable to type 'MapStateToProps<ISideMenu, ISideMenuState, {}>'.
Types of parameters 'state' and 'state' are incompatible.
Type '{}' is not
assignable to type 'ISideMenuState'.
Property 'fileExplorer' is missing in type '{}'.
And these are the two interfaces I am using in the react component:
export interface ISideMenu {
fileExplorerInfo: FileExplorerReducerState | null;
}
export interface ISideMenuState {
fileExplorer: FileDirectoryTree | null;
}
Any insight into this error will be greatly appreciated!
As of React-Redux v8, React-Redux is fully written in TypeScript, and the types are included in the published package. The types also export some helpers to make it easier to write typesafe interfaces between your Redux store and your React components.
The connect() function connects a React component to a Redux store. It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.
When using generics, you are getting the place of interfaces wrong:
When you declare your React component:
class Comp extends Component<ICompProps, ICompState>
With ICompProps
and ICompState
are your component's props and internal state respectively.
When you use connect:
connect<IMapStateToProps, IMapDispatchToProps, ICompProps, IReduxState>
IMapStateToProps
represents what is returned by your mapStateToProps()
function.
IMapDispatchToProps
represents what is returned by your mapDispatchToProps()
function.
ICompProps
represents your React component props (same as above)
IReduxState
represents your App's Redux State
So in your particular example:
When declaring your React component:
class SideMenu extends Component<ISideMenu, {}>
Use ISideMenu
for the props and {}
(empty state) for the state as you don't use any state.
When using connect:
connect<ISideMenu, {}, ISideMenu, ISideMenuState>(mapStateToProps)(SideMenu);
You can use ISideMenu
as both your React component props and the object returned by mapStateToProps
. But in practice it might be best to create 2 separate interfaces.
In my apps, I usually can't be bothered typing the mapStateToProps
return object so I simply use:
connect<{}, {}, ISideMenu, ISideMenuState>(mapStateToProps)(SideMenu);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With