From 6288c788f4f49ca606571868abcc5af6cc55d5e9 Mon Sep 17 00:00:00 2001 From: tkqubo Date: Mon, 21 Sep 2015 14:58:43 +0900 Subject: [PATCH 1/6] Add files --- react-redux/react-redux-tests.ts | 27 +++++++++++++++++++++++++++ react-redux/react-redux.d.ts | 8 ++++++++ 2 files changed, 35 insertions(+) create mode 100644 react-redux/react-redux-tests.ts create mode 100644 react-redux/react-redux.d.ts diff --git a/react-redux/react-redux-tests.ts b/react-redux/react-redux-tests.ts new file mode 100644 index 000000000..5de0be520 --- /dev/null +++ b/react-redux/react-redux-tests.ts @@ -0,0 +1,27 @@ +/// +/// + +import { Component } from 'react'; +import { connect } from 'react-redux'; + +function mapStateToProps(state: any): any { + return { + value: state.counter + }; +} + +let increment: Function; +function mapDispatchToProps(dispatch: any): any { + return { + onIncrement: () => dispatch(increment()) + }; +} + +export class Counter extends Component { + +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Counter); diff --git a/react-redux/react-redux.d.ts b/react-redux/react-redux.d.ts new file mode 100644 index 000000000..05ce9fcb0 --- /dev/null +++ b/react-redux/react-redux.d.ts @@ -0,0 +1,8 @@ +// Type definitions for react-redux +// Project: https://github.com/rackt/react-redux +// Definitions by: Qubo +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module "react-redux" { + export function connect(...functions: Function[]): (t: T) => T; +} From 33dbe07ff59c6024abf1ac179ce0502372f0b21c Mon Sep 17 00:00:00 2001 From: tkqubo Date: Mon, 21 Sep 2015 17:34:28 +0900 Subject: [PATCH 2/6] Adding react-redux --- ...t-redux-tests.ts => react-redux-tests.tsx} | 27 +++++++++++++++++-- react-redux/react-redux.d.ts | 22 ++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) rename react-redux/{react-redux-tests.ts => react-redux-tests.tsx} (53%) diff --git a/react-redux/react-redux-tests.ts b/react-redux/react-redux-tests.tsx similarity index 53% rename from react-redux/react-redux-tests.ts rename to react-redux/react-redux-tests.tsx index 5de0be520..852c0822a 100644 --- a/react-redux/react-redux-tests.ts +++ b/react-redux/react-redux-tests.tsx @@ -1,8 +1,25 @@ /// /// +/// import { Component } from 'react'; -import { connect } from 'react-redux'; +import * as React from 'react'; +import { Store } from 'redux'; +import { connect, Provider } from 'react-redux'; + +class MyRootComponent extends Component { + +} +var store: Store; + +React.render( + + {() => } + , + document.body +); + + function mapStateToProps(state: any): any { return { @@ -18,10 +35,16 @@ function mapDispatchToProps(dispatch: any): any { } export class Counter extends Component { - } export default connect( mapStateToProps, mapDispatchToProps )(Counter); + +@connect(mapStateToProps) +export class Counter2 extends Component { +} + + + diff --git a/react-redux/react-redux.d.ts b/react-redux/react-redux.d.ts index 05ce9fcb0..1a6a5cba1 100644 --- a/react-redux/react-redux.d.ts +++ b/react-redux/react-redux.d.ts @@ -3,6 +3,26 @@ // Definitions by: Qubo // Definitions: https://github.com/borisyankov/DefinitelyTyped +/// + declare module "react-redux" { - export function connect(...functions: Function[]): (t: T) => T; + import { Component } from 'react'; + + export interface ClassDecorator { + (target: TFunction): TFunction|void; + } + + export function connect(...functions: Function[]): ClassDecorator; + + export interface Store { + subscribe: Function; + dispatch: Function; + getState: Function; + } + + export interface Property { + store: Store; + } + + export class Provider extends Component { } } From b83c3b8895a6e697ea76f61af0b2c962f6e769ab Mon Sep 17 00:00:00 2001 From: tkqubo Date: Thu, 24 Sep 2015 00:10:59 +0900 Subject: [PATCH 3/6] Add react-redux --- react-redux/react-redux-tests.tsx | 226 +++++++++++++++++++++++++++--- react-redux/react-redux.d.ts | 2 +- 2 files changed, 209 insertions(+), 19 deletions(-) diff --git a/react-redux/react-redux-tests.tsx b/react-redux/react-redux-tests.tsx index 852c0822a..a8841d080 100644 --- a/react-redux/react-redux-tests.tsx +++ b/react-redux/react-redux-tests.tsx @@ -1,16 +1,105 @@ /// /// /// +/// +/// import { Component } from 'react'; import * as React from 'react'; -import { Store } from 'redux'; +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 { } -var store: Store; +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( @@ -19,32 +108,133 @@ React.render( document.body ); +Router.run(routes, Router.HistoryLocation, (Handler, routerState) => { // note "routerState" here + React.render( + + {() => } // note "routerState" here: important to pass it down + , + document.getElementById('root') + ); +}); +React.render( + + {() => ...} + , + targetEl +); -function mapStateToProps(state: any): any { - return { - value: state.counter - }; +// 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 }; } -let increment: Function; -function mapDispatchToProps(dispatch: any): any { - return { - onIncrement: () => dispatch(increment()) - }; +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) }; } -export class Counter extends Component { +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); } -export default connect( - mapStateToProps, - mapDispatchToProps -)(Counter); +connect(mapStateToProps2, mapDispatchToProps3)(TodoApp); -@connect(mapStateToProps) -export class Counter2 extends Component { +// 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.d.ts b/react-redux/react-redux.d.ts index 1a6a5cba1..454399f83 100644 --- a/react-redux/react-redux.d.ts +++ b/react-redux/react-redux.d.ts @@ -1,4 +1,4 @@ -// Type definitions for react-redux +// Type definitions for react-redux 2.1.2 // Project: https://github.com/rackt/react-redux // Definitions by: Qubo // Definitions: https://github.com/borisyankov/DefinitelyTyped From c5240e2aef1d20e11d10500e8b06df74f3110a64 Mon Sep 17 00:00:00 2001 From: tkqubo Date: Thu, 24 Sep 2015 00:27:47 +0900 Subject: [PATCH 4/6] Remove lines that are not compilable with current version of react-router (?) --- react-redux/react-redux-tests.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/react-redux/react-redux-tests.tsx b/react-redux/react-redux-tests.tsx index a8841d080..6e883d1f0 100644 --- a/react-redux/react-redux-tests.tsx +++ b/react-redux/react-redux-tests.tsx @@ -111,18 +111,23 @@ React.render( Router.run(routes, Router.HistoryLocation, (Handler, routerState) => { // note "routerState" here React.render( - {() => } // note "routerState" here: important to pass it down + {/* + //TODO: error TS2339: Property 'routerState' does not exist on type 'RouteProp'. + {() => } // note "routerState" here: important to pass it down + */} , document.getElementById('root') ); }); -React.render( - - {() => ...} - , - targetEl -); +//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 From 387387b1431b70678c6e81766ba7f220fd779efc Mon Sep 17 00:00:00 2001 From: tkqubo Date: Thu, 24 Sep 2015 00:47:16 +0900 Subject: [PATCH 5/6] Add more detailed typings about connect arguments --- react-redux/react-redux-tests.tsx | 3 +- react-redux/react-redux.d.ts | 52 +++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/react-redux/react-redux-tests.tsx b/react-redux/react-redux-tests.tsx index 6e883d1f0..9bd662295 100644 --- a/react-redux/react-redux-tests.tsx +++ b/react-redux/react-redux-tests.tsx @@ -68,10 +68,9 @@ const targetEl = document.getElementById('root'); React.render(( {() => } - + ), targetEl); - // // API // https://github.com/rackt/react-redux/blob/master/docs/api.md diff --git a/react-redux/react-redux.d.ts b/react-redux/react-redux.d.ts index 454399f83..f1ef5458e 100644 --- a/react-redux/react-redux.d.ts +++ b/react-redux/react-redux.d.ts @@ -4,25 +4,65 @@ // 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; } - export function connect(...functions: Function[]): ClassDecorator; + /** + * 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; - export interface Store { - subscribe: Function; - dispatch: Function; - getState: Function; + 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 { - store: Store; + /** + * 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 { } } From bce79748a1c72fb53fda869331bec9ebb055ad25 Mon Sep 17 00:00:00 2001 From: tkqubo Date: Thu, 24 Sep 2015 00:50:08 +0900 Subject: [PATCH 6/6] Add tscparams file --- react-redux/react-redux-tests.tsx.tscparams | 1 + 1 file changed, 1 insertion(+) create mode 100644 react-redux/react-redux-tests.tsx.tscparams 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