diff --git a/react-redux/react-redux-tests.tsx b/react-redux/react-redux-tests.tsx new file mode 100644 index 000000000..9bd662295 --- /dev/null +++ b/react-redux/react-redux-tests.tsx @@ -0,0 +1,244 @@ +/// +/// +/// +/// +/// + +import { Component } from 'react'; +import * as React from 'react'; +import * as Router from 'react-router'; +import { Route, RouterState } from 'react-router'; +import { Store, Dispatch, bindActionCreators } from 'redux'; +import { connect, Provider } from 'react-redux'; +import objectAssign = require('object-assign'); + +// +// Quick Start +// https://github.com/rackt/react-redux/blob/master/docs/quick-start.md#quick-start +// + +interface CounterState { + counter: number; +} +declare var increment: Function; + +class Counter extends Component { + render() { + return ( + + ); + } +} + +function mapStateToProps(state: CounterState) { + return { + value: state.counter + }; +} + +// Which action creators does it want to receive by props? +function mapDispatchToProps(dispatch: Dispatch) { + return { + onIncrement: () => dispatch(increment()) + }; +} + +connect( + mapStateToProps, + mapDispatchToProps +)(Counter); + + +@connect(mapStateToProps) +class CounterContainer extends Component { + +} + +class App extends Component { + render(): JSX.Element { + // ... + return null; + } +} + +const targetEl = document.getElementById('root'); + +React.render(( + + {() => } + +), targetEl); + +// +// API +// https://github.com/rackt/react-redux/blob/master/docs/api.md +// +declare var routes: Route; +declare var store: Store; +declare var routerState: RouterState; +class MyRootComponent extends Component { + +} +class TodoApp extends Component { + +} +interface TodoState { + todos: string[]|string; +} +interface TodoProps { + userId: number; +} +interface DispatchProps { + addTodo(userId: number, text: string): void; +} +declare var actionCreators: () => { + action: Function; +} +declare var addTodo: () => { type: string; }; +declare var todoActionCreators: { [type: string]: (...args: any[]) => any; }; +declare var counterActionCreators: { [type: string]: (...args: any[]) => any; }; + +React.render( + + {() => } + , + document.body +); + +Router.run(routes, Router.HistoryLocation, (Handler, routerState) => { // note "routerState" here + React.render( + + {/* + //TODO: error TS2339: Property 'routerState' does not exist on type 'RouteProp'. + {() => } // note "routerState" here: important to pass it down + */} + , + document.getElementById('root') + ); +}); + +//TODO: for React Router 1.0 +//TODO: error TS2604: JSX element type 'Router' does not have any construct or call signatures. +//React.render( +// +// {() => ...} +// , +// targetEl +//); + +// Inject just dispatch and don't listen to store + +connect()(TodoApp); + +// Inject dispatch and every field in the global state + +connect((state: TodoState) => state)(TodoApp); + +// Inject dispatch and todos + +function mapStateToProps2(state: TodoState) { + return { todos: state.todos }; +} + +export default connect(mapStateToProps2)(TodoApp); + +// Inject todos and all action creators (addTodo, completeTodo, ...) + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +connect(mapStateToProps2, actionCreators)(TodoApp); + +// Inject todos and all action creators (addTodo, completeTodo, ...) as actions + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mapDispatchToProps2(dispatch: Dispatch) { + return { actions: bindActionCreators(actionCreators, dispatch) }; +} + +connect(mapStateToProps2, mapDispatchToProps2)(TodoApp); + +// Inject todos and a specific action creator (addTodo) + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mapDispatchToProps3(dispatch: Dispatch) { + return bindActionCreators({ addTodo }, dispatch); +} + +connect(mapStateToProps2, mapDispatchToProps3)(TodoApp); + +// Inject todos, todoActionCreators as todoActions, and counterActionCreators as counterActions + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mapDispatchToProps4(dispatch: Dispatch) { + return { + todoActions: bindActionCreators(todoActionCreators, dispatch), + counterActions: bindActionCreators(counterActionCreators, dispatch) + }; +} + +connect(mapStateToProps2, mapDispatchToProps4)(TodoApp); + +// Inject todos, and todoActionCreators and counterActionCreators together as actions + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mapDispatchToProps5(dispatch: Dispatch) { + return { + actions: bindActionCreators(objectAssign({}, todoActionCreators, counterActionCreators), dispatch) + }; +} + +connect(mapStateToProps2, mapDispatchToProps5)(TodoApp); + +// Inject todos, and all todoActionCreators and counterActionCreators directly as props + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mapDispatchToProps6(dispatch: Dispatch) { + return bindActionCreators(objectAssign({}, todoActionCreators, counterActionCreators), dispatch); +} + +connect(mapStateToProps2, mapDispatchToProps6)(TodoApp); + +// Inject todos of a specific user depending on props + +function mapStateToProps3(state: TodoState, ownProps: TodoProps): TodoState { + return { todos: state.todos[ownProps.userId] }; +} + +connect(mapStateToProps3)(TodoApp); + +// Inject todos of a specific user depending on props, and inject props.userId into the action + +//function mapStateToProps(state) { +// return { todos: state.todos }; +//} + +function mergeProps(stateProps: TodoState, dispatchProps: DispatchProps, ownProps: TodoProps): DispatchProps & TodoState { + return objectAssign({}, ownProps, { + todos: stateProps.todos[ownProps.userId], + addTodo: (text: string) => dispatchProps.addTodo(ownProps.userId, text) + }); +} + +connect(mapStateToProps2, actionCreators, mergeProps)(TodoApp); + + + diff --git a/react-redux/react-redux-tests.tsx.tscparams b/react-redux/react-redux-tests.tsx.tscparams new file mode 100644 index 000000000..c90abf04f --- /dev/null +++ b/react-redux/react-redux-tests.tsx.tscparams @@ -0,0 +1 @@ +--target es5 --noImplicitAny --experimentalDecorators --jsx react diff --git a/react-redux/react-redux.d.ts b/react-redux/react-redux.d.ts new file mode 100644 index 000000000..f1ef5458e --- /dev/null +++ b/react-redux/react-redux.d.ts @@ -0,0 +1,68 @@ +// Type definitions for react-redux 2.1.2 +// Project: https://github.com/rackt/react-redux +// Definitions by: Qubo +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +/// +/// + +declare module "react-redux" { + import { Component } from 'react'; + import { Store, Dispatch, ActionCreator } from 'redux'; + + export interface ClassDecorator { + (target: TFunction): TFunction|void; + } + + /** + * Connects a React component to a Redux store. + * @param mapStateToProps + * @param mapDispatchToProps + * @param mergeProps + * @param options + */ + export function connect(mapStateToProps?: MapStateToProps, + mapDispatchToProps?: MapDispatchToPropsFunction|MapDispatchToPropsObject, + mergeProps?: MergeProps, + options?: Options): ClassDecorator; + + interface MapStateToProps { + (state: any, ownProps?: any): any; + } + + interface MapDispatchToPropsFunction { + (dispatch: Dispatch, ownProps?: any): any; + } + + interface MapDispatchToPropsObject { + [name: string]: ActionCreator; + } + + interface MergeProps { + (stateProps: any, dispatchProps: any, ownProps: any): any; + } + + interface Options { + /** + * If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps, + * preventing unnecessary updates, assuming that the component is a “pure” component + * and does not rely on any input or state other than its props and the selected Redux store’s state. + * Defaults to true. + * @default true + */ + pure: boolean; + } + + export interface Property { + /** + * The single Redux store in your application. + */ + store?: Store; + children?: Function; + } + + /** + * Makes the Redux store available to the connect() calls in the component hierarchy below. + */ + export class Provider extends Component { } +}