Last active
October 25, 2016 09:11
-
-
Save TomMarius/ba17372660a1b755bb5448f466f1ac58 to your computer and use it in GitHub Desktop.
Typescript 2.0, React, Redux, React-Redux - a complete, yet simple example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React from "react"; | |
| import { render } from "react-dom"; | |
| import { createStore, Action, Dispatch } from "redux"; | |
| import { connect, Provider } from "react-redux"; | |
| // my state | |
| interface State | |
| { | |
| number: number; | |
| } | |
| const initialState: State = { number: 0 }; | |
| // action(s) | |
| const ADD_ACTION = "ADD"; // action type name | |
| interface AddAction extends Action | |
| { | |
| number: number; | |
| } | |
| function add(number: number): AddAction | |
| { | |
| return { | |
| type: ADD_ACTION, | |
| number: number | |
| }; | |
| } | |
| // reducer | |
| function reducer(state = initialState, action: Action): State | |
| { | |
| switch (action.type) | |
| { | |
| case ADD_ACTION: | |
| return Object.assign({}, state, { number: state.number + (action as AddAction).number }); // always copy the state, never return a reference to the previous one | |
| default: | |
| return state; | |
| } | |
| } | |
| // store | |
| const store = createStore(reducer, initialState); | |
| // react | |
| interface StateProps // global type, import in every component | |
| { | |
| state: State; | |
| } | |
| interface DispatchProps // global type, import in every component | |
| { | |
| dispatch: Dispatch<any>; | |
| } | |
| // local component - e.g. NumberView.tsx | |
| export interface NumberViewProps | |
| { | |
| prefix: string; | |
| } | |
| // no export there, this is a private class (could be a stateless component too) | |
| class NumberViewComponent extends React.Component<StateProps & DispatchProps & NumberViewProps, {}> // note the intersection and empty interface as the state | |
| { | |
| public render(): JSX.Element | |
| { | |
| return ( | |
| <span onClick={ () => this.props.dispatch(add(1)) }>{ this.props.prefix }{ this.props.state.number }</span> | |
| ); | |
| } | |
| } | |
| // exported decorated component, this time no intersection so the props are properly set (don't contain ) | |
| export const NumberView = connect<StateProps, DispatchProps, NumberViewProps>((state: State) => ({ state }))(NumberViewComponent); | |
| // use the class! | |
| render(<Provider store={ store }><NumberView prefix={ "Number: " } /></Provider>, document.getElementById("app")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment