Update flow-typed definitions for redux to include thunk actions
This commit is contained in:
Родитель
b0318a9e7e
Коммит
fd5e88c61d
|
@ -2,90 +2,134 @@
|
|||
// flow-typed version: a165222d28/redux_v3.x.x/flow_>=v0.33.x
|
||||
|
||||
declare module 'redux' {
|
||||
|
||||
/*
|
||||
|
||||
S = State
|
||||
A = Action
|
||||
D = Dispatch
|
||||
R = Result of a thunk action
|
||||
|
||||
*/
|
||||
|
||||
declare type GetState<S> = () => S;
|
||||
declare type ThunkAction<S, A, R> = (
|
||||
dispatch: Dispatch<S, A>,
|
||||
GetState<S>,
|
||||
) => R;
|
||||
declare type ThunkDispatch<S, A> = <R>(action: ThunkAction<S, A, R>) => R;
|
||||
declare type DispatchAPI<A> = (action: A) => A;
|
||||
declare type Dispatch<A: { type: $Subtype<string> }> = DispatchAPI<A>;
|
||||
declare type PlainDispatch<A: {type: $Subtype<string>}> = DispatchAPI<A>;
|
||||
declare type Dispatch<S, A> = PlainDispatch<A> & ThunkDispatch<S, A>;
|
||||
|
||||
declare type MiddlewareAPI<S, A, D = Dispatch<A>> = {
|
||||
dispatch: D;
|
||||
getState(): S;
|
||||
declare type MiddlewareAPI<S, A, D = Dispatch<S, A>> = {
|
||||
dispatch: D,
|
||||
getState(): S,
|
||||
};
|
||||
|
||||
declare type Store<S, A, D = Dispatch<A>> = {
|
||||
declare type Store<S, A, D = Dispatch<S, A>> = {
|
||||
// rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages)
|
||||
dispatch: D;
|
||||
getState(): S;
|
||||
subscribe(listener: () => void): () => void;
|
||||
replaceReducer(nextReducer: Reducer<S, A>): void
|
||||
dispatch: D,
|
||||
getState(): S,
|
||||
subscribe(listener: () => void): () => void,
|
||||
replaceReducer(nextReducer: Reducer<S, A>): void,
|
||||
};
|
||||
|
||||
declare type Reducer<S, A> = (state: S, action: A) => S;
|
||||
|
||||
declare type CombinedReducer<S, A> = (state: $Shape<S> & {} | void, action: A) => S;
|
||||
declare type CombinedReducer<S, A> = (
|
||||
state: ($Shape<S> & {}) | void,
|
||||
action: A,
|
||||
) => S;
|
||||
|
||||
declare type Middleware<S, A, D = Dispatch<A>> =
|
||||
(api: MiddlewareAPI<S, A, D>) =>
|
||||
(next: D) => D;
|
||||
declare type Middleware<S, A, D = Dispatch<S, A>> = (
|
||||
api: MiddlewareAPI<S, A, D>,
|
||||
) => (next: D) => D;
|
||||
|
||||
declare type StoreCreator<S, A, D = Dispatch<A>> = {
|
||||
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
declare type StoreCreator<S, A, D = Dispatch<S, A>> = {
|
||||
(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>,
|
||||
(
|
||||
reducer: Reducer<S, A>,
|
||||
preloadedState: S,
|
||||
enhancer?: StoreEnhancer<S, A, D>,
|
||||
): Store<S, A, D>,
|
||||
};
|
||||
|
||||
declare type StoreEnhancer<S, A, D = Dispatch<A>> = (next: StoreCreator<S, A, D>) => StoreCreator<S, A, D>;
|
||||
declare type StoreEnhancer<S, A, D = Dispatch<S, A>> = (
|
||||
next: StoreCreator<S, A, D>,
|
||||
) => StoreCreator<S, A, D>;
|
||||
|
||||
declare function createStore<S, A, D>(reducer: Reducer<S, A>, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
declare function createStore<S, A, D>(reducer: Reducer<S, A>, preloadedState: S, enhancer?: StoreEnhancer<S, A, D>): Store<S, A, D>;
|
||||
declare function createStore<S, A, D>(
|
||||
reducer: Reducer<S, A>,
|
||||
enhancer?: StoreEnhancer<S, A, D>,
|
||||
): Store<S, A, D>;
|
||||
declare function createStore<S, A, D>(
|
||||
reducer: Reducer<S, A>,
|
||||
preloadedState: S,
|
||||
enhancer?: StoreEnhancer<S, A, D>,
|
||||
): Store<S, A, D>;
|
||||
|
||||
declare function applyMiddleware<S, A, D>(...middlewares: Array<Middleware<S, A, D>>): StoreEnhancer<S, A, D>;
|
||||
declare function applyMiddleware<S, A, D>(
|
||||
...middlewares: Array<Middleware<S, A, D>>
|
||||
): StoreEnhancer<S, A, D>;
|
||||
|
||||
declare type ActionCreator<A, B> = (...args: Array<B>) => A;
|
||||
declare type ActionCreators<K, A> = { [key: K]: ActionCreator<A, any> };
|
||||
declare type ActionCreators<K, A> = {[key: K]: ActionCreator<A, any>};
|
||||
|
||||
declare function bindActionCreators<A, C: ActionCreator<A, any>, D: DispatchAPI<A>>(actionCreator: C, dispatch: D): C;
|
||||
declare function bindActionCreators<A, K, C: ActionCreators<K, A>, D: DispatchAPI<A>>(actionCreators: C, dispatch: D): C;
|
||||
declare function bindActionCreators<
|
||||
S,
|
||||
A,
|
||||
C: ActionCreator<A, any>,
|
||||
D: DispatchAPI<A>,
|
||||
>(
|
||||
actionCreator: C,
|
||||
dispatch: D,
|
||||
): C;
|
||||
declare function bindActionCreators<
|
||||
S,
|
||||
A,
|
||||
K,
|
||||
C: ActionCreators<K, A>,
|
||||
D: DispatchAPI<A>,
|
||||
>(
|
||||
actionCreators: C,
|
||||
dispatch: D,
|
||||
): C;
|
||||
|
||||
declare function combineReducers<O: Object, A>(reducers: O): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
|
||||
declare function combineReducers<O: Object, A>(
|
||||
reducers: O,
|
||||
): CombinedReducer<$ObjMap<O, <S>(r: Reducer<S, any>) => S>, A>;
|
||||
|
||||
declare function compose<A, B>(ab: (a: A) => B): (a: A) => B
|
||||
declare function compose<A, B>(ab: (a: A) => B): (a: A) => B;
|
||||
declare function compose<A, B, C>(
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => C
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => C;
|
||||
declare function compose<A, B, C, D>(
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => D
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => D;
|
||||
declare function compose<A, B, C, D, E>(
|
||||
de: (d: D) => E,
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => E
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => E;
|
||||
declare function compose<A, B, C, D, E, F>(
|
||||
ef: (e: E) => F,
|
||||
de: (d: D) => E,
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => F
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => F;
|
||||
declare function compose<A, B, C, D, E, F, G>(
|
||||
fg: (f: F) => G,
|
||||
ef: (e: E) => F,
|
||||
de: (d: D) => E,
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => G
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => G;
|
||||
declare function compose<A, B, C, D, E, F, G, H>(
|
||||
gh: (g: G) => H,
|
||||
fg: (f: F) => G,
|
||||
|
@ -93,8 +137,8 @@ declare module 'redux' {
|
|||
de: (d: D) => E,
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => H
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => H;
|
||||
declare function compose<A, B, C, D, E, F, G, H, I>(
|
||||
hi: (h: H) => I,
|
||||
gh: (g: G) => H,
|
||||
|
@ -103,7 +147,6 @@ declare module 'redux' {
|
|||
de: (d: D) => E,
|
||||
cd: (c: C) => D,
|
||||
bc: (b: B) => C,
|
||||
ab: (a: A) => B
|
||||
): (a: A) => I
|
||||
|
||||
ab: (a: A) => B,
|
||||
): (a: A) => I;
|
||||
}
|
||||
|
|
66
src/App.js
66
src/App.js
|
@ -12,7 +12,13 @@ import {
|
|||
localUrlFromVersion,
|
||||
requestOngoingVersions,
|
||||
} from './actions.js';
|
||||
import type {Dispatch, OngoingVersions, Status, Statuses} from './types.js';
|
||||
import type {
|
||||
Dispatch,
|
||||
OngoingVersions,
|
||||
State,
|
||||
Status,
|
||||
Statuses,
|
||||
} from './types.js';
|
||||
|
||||
function requestNotificationPermission(): void {
|
||||
if (
|
||||
|
@ -43,7 +49,7 @@ const parseUrl = (
|
|||
class ConnectedApp extends React.Component<{dispatch: Dispatch}, void> {
|
||||
refreshIntervalId: ?number;
|
||||
|
||||
constructor(props): void {
|
||||
constructor(props: {dispatch: Dispatch}): void {
|
||||
super(props);
|
||||
this.refreshIntervalId = null;
|
||||
}
|
||||
|
@ -107,28 +113,24 @@ const App = connect()(ConnectedApp);
|
|||
|
||||
const VersionInput = connect(
|
||||
// mapStateToProps
|
||||
state => {
|
||||
return {
|
||||
value: state.versionInput,
|
||||
};
|
||||
},
|
||||
(state: State) => ({
|
||||
value: state.versionInput,
|
||||
}),
|
||||
// mapDispatchToProps
|
||||
dispatch => {
|
||||
return {
|
||||
onSubmit: (e: SyntheticEvent<HTMLInputElement>): void => {
|
||||
e.preventDefault();
|
||||
dispatch(submitVersion());
|
||||
dispatch(updateUrl());
|
||||
},
|
||||
handleSearchBoxChange: (e: SyntheticEvent<HTMLInputElement>): void => {
|
||||
dispatch(updateVersionInput(e.currentTarget.value));
|
||||
},
|
||||
handleDismissSearchBoxVersion: (): void => {
|
||||
window.location.hash = '';
|
||||
dispatch(setVersion(''));
|
||||
},
|
||||
};
|
||||
},
|
||||
(dispatch: Dispatch) => ({
|
||||
onSubmit: (e: SyntheticEvent<HTMLInputElement>): void => {
|
||||
e.preventDefault();
|
||||
dispatch(submitVersion());
|
||||
dispatch(updateUrl());
|
||||
},
|
||||
handleSearchBoxChange: (e: SyntheticEvent<HTMLInputElement>): void => {
|
||||
dispatch(updateVersionInput(e.currentTarget.value));
|
||||
},
|
||||
handleDismissSearchBoxVersion: (): void => {
|
||||
window.location.hash = '';
|
||||
dispatch(setVersion(''));
|
||||
},
|
||||
}),
|
||||
)(SearchForm);
|
||||
|
||||
type SearchFormProps = {
|
||||
|
@ -188,11 +190,9 @@ function Spinner() {
|
|||
|
||||
const SideBar = connect(
|
||||
// mapStateToProps
|
||||
state => {
|
||||
return {
|
||||
versions: state.latestChannelVersions,
|
||||
};
|
||||
},
|
||||
(state: State) => ({
|
||||
versions: state.latestChannelVersions,
|
||||
}),
|
||||
// mapDispatchToProps
|
||||
null,
|
||||
)(ReleasesMenu);
|
||||
|
@ -225,12 +225,10 @@ function ReleaseItem({title, version}: {title: string, version: string}) {
|
|||
|
||||
const CurrentRelease = connect(
|
||||
// mapStateToProps
|
||||
state => {
|
||||
return {
|
||||
statuses: state.statuses,
|
||||
version: state.version,
|
||||
};
|
||||
},
|
||||
(state: State) => ({
|
||||
statuses: state.statuses,
|
||||
version: state.version,
|
||||
}),
|
||||
// mapDispatchToProps
|
||||
null,
|
||||
)(Dashboard);
|
||||
|
|
|
@ -14,6 +14,7 @@ import type {
|
|||
SetVersion,
|
||||
Statuses,
|
||||
SubmitVersion,
|
||||
ThunkAction,
|
||||
UpdateLatestChannelVersions,
|
||||
UpdateStatuses,
|
||||
UpdateVersionInput,
|
||||
|
@ -73,7 +74,7 @@ function fetchStatus(version: string): Promise<*> {
|
|||
);
|
||||
}
|
||||
|
||||
export function requestStatus(version: ?string) {
|
||||
export function requestStatus(version: ?string): ThunkAction<void> {
|
||||
const notifyChanges = changed => {
|
||||
// $FlowFixMe
|
||||
if (Notification.permission === 'granted') {
|
||||
|
@ -131,7 +132,7 @@ export function requestOngoingVersions() {
|
|||
// We do that in a thunk action to have access to the state via "getState".
|
||||
export const localUrlFromVersion = (version: string) =>
|
||||
`#pollbot/firefox/${version}`;
|
||||
export function updateUrl() {
|
||||
export function updateUrl(): ThunkAction<void> {
|
||||
return function(dispatch: Dispatch, getState: GetState) {
|
||||
window.location.hash = localUrlFromVersion(getState().version);
|
||||
};
|
||||
|
|
15
src/types.js
15
src/types.js
|
@ -1,5 +1,10 @@
|
|||
// @flow
|
||||
import type {Store as ReduxStore, Dispatch as ReduxDispatch} from 'redux';
|
||||
import type {
|
||||
Store as ReduxStore,
|
||||
ThunkAction as ReduxThunkAction,
|
||||
Dispatch as ReduxDispatch,
|
||||
GetState as ReduxGetState,
|
||||
} from 'redux';
|
||||
|
||||
/*
|
||||
* state types
|
||||
|
@ -68,9 +73,9 @@ export type Action =
|
|||
| UpdateStatuses;
|
||||
|
||||
/*
|
||||
* types
|
||||
* Redux types
|
||||
*/
|
||||
export type GetState = () => State;
|
||||
export type GetState = ReduxGetState<State>;
|
||||
export type ThunkAction<Result> = ReduxThunkAction<State, Action, Result>;
|
||||
export type Store = ReduxStore<State, Action>;
|
||||
export type Dispatch = ReduxDispatch<Action> & Thunk<Action>;
|
||||
export type Thunk<A> = ((Dispatch, GetState) => Promise<void> | void) => A;
|
||||
export type Dispatch = ReduxDispatch<State, Action>;
|
||||
|
|
Загрузка…
Ссылка в новой задаче