From fe7d4210a51fdfddf1132d0d463a393b7bb3e0f8 Mon Sep 17 00:00:00 2001 From: Ramon de Klein Date: Thu, 6 Dec 2018 22:38:38 +0100 Subject: [PATCH] Improved typing. --- README.md | 49 ++++++++++++++++++++-------------------- src/components/Hello.tsx | 38 ++++++++++++++++++------------- src/containers/Hello.tsx | 6 ++--- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 0793532..3c1eaa9 100644 --- a/README.md +++ b/README.md @@ -594,12 +594,10 @@ Components are often data-agnostic, and work mostly at a presentational level. You can read more about this concept on [Dan Abramov's article *Presentational and Container Components*](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0). First let's update `src/components/Hello.tsx` so that it can modify state. -We'll add two optional callback properties to `Props` named `onIncrement` and `onDecrement`: +We'll create the `DispatchProps` interface that holds two optional callback properties named `onIncrement` and `onDecrement`: ```ts -export interface Props { - name: string; - enthusiasmLevel?: number; +export interface DispatchProps { onIncrement?: () => void; onDecrement?: () => void; } @@ -608,22 +606,25 @@ export interface Props { Then we'll bind those callbacks to two new buttons that we'll add into our component. ```ts -function Hello({ name, enthusiasmLevel = 1, onIncrement, onDecrement }: Props) { - if (enthusiasmLevel <= 0) { - throw new Error('You could be a little more enthusiastic. :D'); - } +export class Hello extends React.Component { + render() { + const {enthusiasmLevel = 1} = this.props; + if (enthusiasmLevel <= 0) { + throw new Error('You could be a little more enthusiastic. :D'); + } - return ( -
-
- Hello {name + getExclamationMarks(enthusiasmLevel)} -
-
- - + return ( +
+
+ Hello {this.props.name + getExclamationMarks(enthusiasmLevel)} +
+
+ + +
-
- ); + ); + } } ``` @@ -634,7 +635,7 @@ Now that our component is updated, we're ready to wrap it into a container. Let's create a file named `src/containers/Hello.tsx` and start off with the following imports. ```ts -import Hello from '../components/Hello'; +import { Hello, Props, DispatchProps } from '../components/Hello'; import * as actions from '../actions/'; import { StoreState } from '../types/index'; import { connect, Dispatch } from 'react-redux'; @@ -652,7 +653,7 @@ Our `Hello` component, on the other hand, expected a `name` and an `enthusiasmLe Let's go ahead and write that. ```ts -export function mapStateToProps({ enthusiasmLevel, languageName }: StoreState) { +export function mapStateToProps({ enthusiasmLevel, languageName }: StoreState): Props { return { enthusiasmLevel, name: languageName, @@ -666,7 +667,7 @@ Namely, we still want to pass in the `onIncrement` and `onDecrement` callbacks. This dispatcher function can pass actions into our store to make updates, so we can create a pair of callbacks that will call the dispatcher as necessary. ```ts -export function mapDispatchToProps(dispatch: Dispatch) { +export function mapDispatchToProps(dispatch: Dispatch): DispatchProps { return { onIncrement: () => dispatch(actions.incrementEnthusiasm()), onDecrement: () => dispatch(actions.decrementEnthusiasm()), @@ -687,19 +688,19 @@ When we're finished, our file should look like this: ```ts // src/containers/Hello.tsx -import Hello from '../components/Hello'; +import { Hello, Props, DispatchProps } from '../components/Hello'; import * as actions from '../actions/'; import { StoreState } from '../types/index'; import { connect, Dispatch } from 'react-redux'; -export function mapStateToProps({ enthusiasmLevel, languageName }: StoreState) { +export function mapStateToProps({ enthusiasmLevel, languageName }: StoreState): Props { return { enthusiasmLevel, name: languageName, } } -export function mapDispatchToProps(dispatch: Dispatch) { +export function mapDispatchToProps(dispatch: Dispatch): DispatchProps { return { onIncrement: () => dispatch(actions.incrementEnthusiasm()), onDecrement: () => dispatch(actions.decrementEnthusiasm()), diff --git a/src/components/Hello.tsx b/src/components/Hello.tsx index 1f6d8fa..aea14c8 100644 --- a/src/components/Hello.tsx +++ b/src/components/Hello.tsx @@ -4,26 +4,32 @@ import './Hello.css'; export interface Props { name: string; enthusiasmLevel?: number; - onIncrement?: () => void; - onDecrement?: () => void; + } + +export interface DispatchProps { + onDecrement?: () => object; + onIncrement?: () => object; } -function Hello({ name, enthusiasmLevel = 1, onIncrement, onDecrement }: Props) { - if (enthusiasmLevel <= 0) { - throw new Error('You could be a little more enthusiastic. :D'); - } +export class Hello extends React.Component { + render() { + const {enthusiasmLevel = 1} = this.props; + if (enthusiasmLevel <= 0) { + throw new Error('You could be a little more enthusiastic. :D'); + } - return ( -
-
- Hello {name + getExclamationMarks(enthusiasmLevel)} + return ( +
+
+ Hello {this.props.name + getExclamationMarks(enthusiasmLevel)} +
+
+ + +
-
- - -
-
- ); + ); + } } export default Hello; diff --git a/src/containers/Hello.tsx b/src/containers/Hello.tsx index 8c5082a..bbcd5ab 100644 --- a/src/containers/Hello.tsx +++ b/src/containers/Hello.tsx @@ -1,16 +1,16 @@ -import Hello from '../components/Hello'; +import { Hello, Props, DispatchProps } from '../components/Hello'; import * as actions from '../actions/'; import { StoreState } from '../types/index'; import { connect, Dispatch } from 'react-redux'; -export function mapStateToProps({ enthusiasmLevel, languageName }: StoreState) { +function mapStateToProps({ enthusiasmLevel, languageName }: StoreState): Props { return { enthusiasmLevel, name: languageName, }; } -export function mapDispatchToProps(dispatch: Dispatch) { +function mapDispatchToProps(dispatch: Dispatch): DispatchProps { return { onIncrement: () => dispatch(actions.incrementEnthusiasm()), onDecrement: () => dispatch(actions.decrementEnthusiasm()),