TypeScript with React: Components
Posted
This is the way I’m currently declaring components when working with TypeScript and React.
To define a React.FunctionComponent<>
connected to Redux using hooks:
interface IProps {
title: string;
}
export const MyComponent: React.FunctionComponent<IProps> = ({
title
}) => {
const [content, setContent] = useState(null);
const comments = useSelector((state: TAppState) => state.comments);
const dispatch = useDispatch();
return (
<button onClick={() => dispatch(doSomething())}>Save</button>
);
};
To define a React.Component<>
connected to Redux with properties and state:
// updateTitle is a function defined in a separate file
interface IProps {
updateTitle: typeof updateTitle;
title: string;
}
interface IState {
// ...
}
class MyComponent extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = { /* ... */ };
this.onClick = this.onClick.bind(this);
}
onClick() {
this.props.updateTitle("Updated title!");
}
render() {
return (
<div>
<span>{this.props.title}</span>
</div>
);
}
}
// TAppState should be replaced by the type of the global state
function mapStateToProps(state: TAppState) {
return {
title: state.title
};
}
// TAction should be replaced with the type grouping the actions that can be
// bound
function mapDispatchToProps(dispatch: ThunkDispatch<any, any, TActions>) {
return bindActionCreators(
{
updateTitle
},
dispatch
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(AdminEditPost);
Conventions
- Methods that are meant to handle events should:
- Start with
on
(e.g.onSaveButtonClick
). - Be bound in the constructor to
this
, to avoid the arrow functions insiderender()
.
- Start with