diff --git a/README.md b/README.md
index 17d8ae9..8849b7e 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
* [react](https://github.com/facebook/react)
* [react-router](https://github.com/ReactTraining/react-router)
* [react-router-dom](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom)
+* [redux](https://github.com/reduxjs/redux)
+* [react-redux](https://github.com/reduxjs/react-redux)
## DevDependencies
* [prettier](https://github.com/prettier/prettier)
diff --git a/index.html b/index.html
index aefb0b8..a2de2f3 100644
--- a/index.html
+++ b/index.html
@@ -5,14 +5,6 @@
-
-
Starter
diff --git a/package.json b/package.json
index 904664e..24cf2bc 100644
--- a/package.json
+++ b/package.json
@@ -25,10 +25,15 @@
]
},
"dependencies": {
+ "deox": "^1.4.0",
"react": "^16.4.2",
"react-dom": "^16.4.2",
+ "react-redux": "^7.0.2",
"react-router": "^4.3.1",
- "react-router-dom": "^4.3.1"
+ "react-router-dom": "^4.3.1",
+ "redux": "^4.0.1",
+ "redux-react-hook": "^3.3.1",
+ "redux-saga": "^1.0.2"
},
"devDependencies": {
"@types/enzyme": "^3.9.0",
@@ -36,6 +41,7 @@
"@types/jest": "^24.0.9",
"@types/react": "^16.4.11",
"@types/react-dom": "^16.0.7",
+ "@types/react-redux": "^7.0.8",
"@types/react-router": "^4.4.4",
"@types/react-router-dom": "^4.3.1",
"enzyme": "^3.9.0",
diff --git a/src/configureStore.ts b/src/configureStore.ts
new file mode 100644
index 0000000..f6fae52
--- /dev/null
+++ b/src/configureStore.ts
@@ -0,0 +1,20 @@
+import { createStore, Dispatch, applyMiddleware } from 'redux';
+
+import { rootReducer } from './rootReducer';
+import { UserState } from './modules/user/reducer/user.reducer';
+import { default as createSagaMiddleware } from '@redux-saga/core';
+import rootSaga from './rootSaga';
+
+export interface ConnectedReduxProps {
+ dispatch: Dispatch;
+}
+
+export interface ApplicationState {
+ userState: UserState;
+}
+
+const sagaMiddleware = createSagaMiddleware();
+
+export const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
+
+sagaMiddleware.run(rootSaga);
diff --git a/src/index.tsx b/src/index.tsx
index d7e4b45..1391a06 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,15 +1,19 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
-
+import { Provider } from 'react-redux';
+import { StoreContext } from 'redux-react-hook';
declare let module: any;
import { App } from './App';
+import { store } from './configureStore';
const RenderApp = () => (
-
-
-
+
+
+
+
+
);
ReactDOM.render(, document.getElementById('root') as HTMLElement);
diff --git a/src/modules/user/reducer/user.reducer.ts b/src/modules/user/reducer/user.reducer.ts
new file mode 100644
index 0000000..147e615
--- /dev/null
+++ b/src/modules/user/reducer/user.reducer.ts
@@ -0,0 +1,19 @@
+import { User, createUser, createUserSucceeded } from '../user.actions';
+import { createReducer } from 'deox';
+
+export interface UserState {
+ user: User;
+}
+
+const userDefaultState: UserState = {
+ user: {
+ firstName: 'john',
+ lastName: 'doe',
+ },
+};
+
+export const userReducer = createReducer(userDefaultState, handle => [
+ handle(createUserSucceeded, (state, action) => {
+ return { ...state, user: action.payload };
+ }),
+]);
diff --git a/src/modules/user/sagas/user.sagas.test.ts b/src/modules/user/sagas/user.sagas.test.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/modules/user/sagas/user.sagas.ts b/src/modules/user/sagas/user.sagas.ts
new file mode 100644
index 0000000..d2a0028
--- /dev/null
+++ b/src/modules/user/sagas/user.sagas.ts
@@ -0,0 +1,27 @@
+import { takeLatest, call, put } from 'redux-saga/effects';
+import {
+ ActionTypeKeys,
+ createUserFailed,
+ createUserSucceeded,
+ User,
+ CreateUserRequestedAction,
+} from '../user.actions';
+import { userEditRequest } from '../user.api';
+
+export function* userEditSaga(action: CreateUserRequestedAction) {
+ try {
+ // define type explicitly because of lack of return types of generators:
+ // https://github.com/redux-saga/redux-saga/issues/1286#issuecomment-482866473
+ const fetchedUser: User = yield call(userEditRequest, {
+ firstName: 'nico',
+ lastName: 'peham',
+ });
+ yield put(createUserSucceeded(fetchedUser));
+ } catch (error) {
+ yield put(createUserFailed());
+ }
+}
+
+export const userSagas = [
+ takeLatest(ActionTypeKeys.CreateUserRequested, userEditSaga),
+];
diff --git a/src/modules/user/scenes/UserEdit.scene.tsx b/src/modules/user/scenes/userEdit/UserEdit.scene.tsx
similarity index 66%
rename from src/modules/user/scenes/UserEdit.scene.tsx
rename to src/modules/user/scenes/userEdit/UserEdit.scene.tsx
index c1eb011..09f81a0 100644
--- a/src/modules/user/scenes/UserEdit.scene.tsx
+++ b/src/modules/user/scenes/userEdit/UserEdit.scene.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
-import { SceneParams } from '../../../shared/types/routing';
+import { SceneParams } from '../../../../shared/types/routing';
+import { UserEditFormContainer } from './userEditForm/UserEditForm.container';
export interface UserEditSceneParams extends SceneParams {
userId: string;
@@ -16,6 +17,9 @@ export const UserEditSene: React.SFC<
userId --> {userId}
projId --> {projId}
+
+
+
);
};
diff --git a/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx
new file mode 100644
index 0000000..63c4fe5
--- /dev/null
+++ b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.container.tsx
@@ -0,0 +1,52 @@
+// tslint:disable-next-line:import-name
+import React, { useCallback } from 'react';
+
+import { ApplicationState } from '../../../../../configureStore';
+import { UserEditForm } from './UserEditForm';
+import {
+ User,
+ createUser,
+ createUserRequested,
+ createUserSucceeded,
+} from '../../../user.actions';
+// tslint:disable-next-line:import-name
+// import React, { useCallback } from 'react';
+import { useMappedState, useDispatch } from 'redux-react-hook';
+
+// const { useCallback } = React;
+
+type UserEditFormContainerStateMapProps = {
+ user: User;
+};
+
+type RegisterFormContainerProps = {
+ passedProp: string;
+};
+
+export const UserEditFormContainer: React.FunctionComponent<
+ RegisterFormContainerProps
+> = ({ passedProp }) => {
+ const mapState = useCallback(
+ (state: ApplicationState): UserEditFormContainerStateMapProps => ({
+ user: state.userState.user,
+ }),
+ [],
+ );
+ const dispatch = useDispatch();
+
+ const { user } = useMappedState(mapState);
+
+ const handleRegisterFormSubmit = (values: User) => {
+ dispatch(createUserRequested(user));
+ };
+
+ return (
+ <>
+ passed: {passedProp}
+ user in state: {JSON.stringify(user)}
+
+
+ {' '}
+ >
+ );
+};
diff --git a/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx
new file mode 100644
index 0000000..5257f86
--- /dev/null
+++ b/src/modules/user/scenes/userEdit/userEditForm/UserEditForm.tsx
@@ -0,0 +1,20 @@
+import * as React from 'react';
+import { User } from '../../../user.actions';
+
+type UserEditFormProps = {
+ onSubmit: (userEdited: User) => void;
+};
+
+export const UserEditForm: React.SFC = ({ onSubmit }) => {
+ const userEdited: User = {
+ firstName: 'susan',
+ lastName: 'jackson',
+ };
+
+ const onUserEdited = () => onSubmit(userEdited);
+ return (
+ <>
+
+ >
+ );
+};
diff --git a/src/modules/user/user.actions.ts b/src/modules/user/user.actions.ts
new file mode 100644
index 0000000..d19f539
--- /dev/null
+++ b/src/modules/user/user.actions.ts
@@ -0,0 +1,37 @@
+import { createAction, Action } from 'deox';
+
+export type User = {
+ firstName: string;
+ lastName: string;
+};
+
+// https://redux.js.org/advanced/async-actions choose!
+export enum ActionTypeKeys {
+ CreateUserRequested = 'USER::CREATE_REQUESTED',
+ CreateUserFailed = 'USER::CREATE_FAILED',
+ CreateUserSucceeded = 'USER::CREATE_SUCCEEDED',
+ CreateUser = 'USER::CREATE',
+}
+
+export const createUser = createAction(
+ ActionTypeKeys.CreateUser,
+ resolve => (user: User) => resolve(user),
+);
+
+export type CreateUserRequestedAction = Action<
+ ActionTypeKeys.CreateUserRequested
+> & {
+ payload: User;
+};
+
+export const createUserRequested = createAction(
+ ActionTypeKeys.CreateUserRequested,
+ resolve => (user: User) => resolve(user),
+);
+
+export const createUserSucceeded = createAction(
+ ActionTypeKeys.CreateUserSucceeded,
+ resolve => (user: User) => resolve(user),
+);
+
+export const createUserFailed = createAction(ActionTypeKeys.CreateUserFailed);
diff --git a/src/modules/user/user.api.ts b/src/modules/user/user.api.ts
new file mode 100644
index 0000000..fa647c7
--- /dev/null
+++ b/src/modules/user/user.api.ts
@@ -0,0 +1,6 @@
+import { User } from './user.actions';
+
+export const userEditRequest = async (user: User): Promise => {
+ const fetchedUser: User = { firstName: 'ie', lastName: 'sei' };
+ return new Promise(resolve => setTimeout(() => resolve(fetchedUser), 1000));
+};
diff --git a/src/modules/user/user.routing.ts b/src/modules/user/user.routing.ts
index da89134..36f3fbc 100644
--- a/src/modules/user/user.routing.ts
+++ b/src/modules/user/user.routing.ts
@@ -1,6 +1,9 @@
-import { UserEditSene, UserEditSceneParams } from './scenes/UserEdit.scene';
import { UserListScene } from './scenes/UserList.scene';
import { AppRoute, IScene } from '../../shared/types/routing';
+import {
+ UserEditSene,
+ UserEditSceneParams,
+} from './scenes/userEdit/UserEdit.scene';
export enum UserRoute {
List = '/user/list',
diff --git a/src/rootReducer.ts b/src/rootReducer.ts
new file mode 100644
index 0000000..96952b2
--- /dev/null
+++ b/src/rootReducer.ts
@@ -0,0 +1,4 @@
+import { combineReducers } from 'redux';
+import { userReducer } from './modules/user/reducer/user.reducer';
+
+export const rootReducer = combineReducers({ userState: userReducer });
diff --git a/src/rootSaga.ts b/src/rootSaga.ts
new file mode 100644
index 0000000..03cb4f4
--- /dev/null
+++ b/src/rootSaga.ts
@@ -0,0 +1,7 @@
+import { userSagas } from './modules/user/sagas/user.sagas';
+import { all } from 'redux-saga/effects';
+
+// https://github.com/redux-saga/redux-saga/issues/160#issuecomment-308540204
+export default function* rootSaga() {
+ yield all([...userSagas]);
+}
diff --git a/src/setupEnzyme.ts b/src/setupEnzyme.ts
index fbb8910..8c03ca5 100644
--- a/src/setupEnzyme.ts
+++ b/src/setupEnzyme.ts
@@ -1,3 +1,3 @@
import { configure } from 'enzyme';
-import * as EnzymeAdapter from 'enzyme-adapter-react-16';
+import EnzymeAdapter from 'enzyme-adapter-react-16';
configure({ adapter: new EnzymeAdapter() });
diff --git a/tsconfig.json b/tsconfig.json
index a25079a..3e28f69 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,6 +12,7 @@
"skipLibCheck": true,
"target": "es5",
"strictNullChecks": true,
+ "esModuleInterop": true
},
"include": ["./src/**/**/*"],
"exclude": ["node_modules"]
diff --git a/tslint.json b/tslint.json
index c296ecb..0bf6d87 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,6 +1,9 @@
{
"extends": ["tslint-config-airbnb", "tslint-react", "tslint-config-prettier"],
"rules": {
- "variable-name": [true, "allow-pascal-case"]
+ "variable-name": [true, "allow-pascal-case"],
+ "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
+ "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies
+ "import-name": false
}
}
diff --git a/yarn.lock b/yarn.lock
index b88b0ab..a034245 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -105,6 +105,13 @@
dependencies:
regenerator-runtime "^0.12.0"
+"@babel/runtime@^7.0.0":
+ version "7.4.4"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
+ integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
"@babel/runtime@^7.1.2":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.3.4.tgz#73d12ba819e365fcf7fd152aed56d6df97d21c83"
@@ -112,6 +119,13 @@
dependencies:
regenerator-runtime "^0.12.0"
+"@babel/runtime@^7.4.3":
+ version "7.4.3"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc"
+ integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA==
+ dependencies:
+ regenerator-runtime "^0.13.2"
+
"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
@@ -309,6 +323,50 @@
"@types/istanbul-lib-coverage" "^1.1.0"
"@types/yargs" "^12.0.9"
+"@redux-saga/core@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.0.2.tgz#4336a5bb4253e5ca69681c25a863fbbc03ea6d88"
+ integrity sha512-AsJYcpuYfM1cmxJvfhXs9HAFSZVEG17TMsLPlXH7+Hq5a5ZP4GqcbtijEmS2AC7NR5lLJHy8csxpqz22PeW5dw==
+ dependencies:
+ "@babel/runtime" "^7.0.0"
+ "@redux-saga/deferred" "^1.0.1"
+ "@redux-saga/delay-p" "^1.0.1"
+ "@redux-saga/is" "^1.0.2"
+ "@redux-saga/symbols" "^1.0.1"
+ "@redux-saga/types" "^1.0.2"
+ redux ">=0.10 <5"
+ typescript-tuple "^2.1.0"
+
+"@redux-saga/deferred@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.0.1.tgz#c895445e486bded90acf0b873b4e978fbfe458c2"
+ integrity sha512-+gW5xQ93QXOOmRLAmX8x2Hx1HpbTG6CM6+HcdTSbJovh4uMWaGyeDECnqXSt8QqA/ja3s2nqYXLqXFKepIQ1hw==
+
+"@redux-saga/delay-p@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.0.1.tgz#d69fc6103c7509ae80faa144ea17bbc69e51e029"
+ integrity sha512-0SnNDyDLUyB4NThtptAwiprNOnbCNhoed/Rp5JwS7SB+a/AdWynVgg/E6BmjsggLFNr07KW0bzn05tsPRBuU7Q==
+ dependencies:
+ "@redux-saga/symbols" "^1.0.1"
+
+"@redux-saga/is@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.0.2.tgz#7f4be014c97061898d7efb11d6c9de31e943ed38"
+ integrity sha512-WnaUOwYvPK2waWjzebT4uhL8zY76XNkzzpJ2EQJe8bN1tByvAjvT7MuJZTSshOhdHL5PsRO0MsH224XIXBJidQ==
+ dependencies:
+ "@redux-saga/symbols" "^1.0.1"
+ "@redux-saga/types" "^1.0.2"
+
+"@redux-saga/symbols@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.0.1.tgz#46512ae1275f88df061c42168d0f600ddb170c1e"
+ integrity sha512-akKkzcVnb1RzJaZV2LQFbi51abvdICMuAKwwLoCjjxLbLAGIw9EJxk5ucNnWSSCEsoEQMeol5tkAcK+Xzuv1Bg==
+
+"@redux-saga/types@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.0.2.tgz#1d94f02800b094753f9271c206a26c2a06ca14ee"
+ integrity sha512-8/qcMh15507AnXJ3lBeuhsdFwnWQqnp68EpUuHlYPixJ5vjVmls7/Jq48cnUlrZI8Jd9U1jkhfCl0gaT5KMgVw==
+
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@@ -376,6 +434,14 @@
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.2.tgz#0e670ea254d559241b6eeb3894f8754991e73220"
integrity sha512-ui3WwXmjTaY73fOQ3/m3nnajU/Orhi6cEu5rzX+BrAAJxa3eITXZ5ch9suPqtM03OWhAHhPSyBGCN4UKoxO20Q==
+"@types/hoist-non-react-statics@^3.3.0":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
"@types/istanbul-lib-coverage@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a"
@@ -415,6 +481,15 @@
dependencies:
"@types/react" "*"
+"@types/react-redux@^7.0.8":
+ version "7.0.8"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.0.8.tgz#c928863058e334d41031c6bedd0f113bc514e234"
+ integrity sha512-vIBC15E84ehN6RzdGwRVa41whp9e4CkfPm+WfD0r6y6vqBf4tQPKZeKEBfLLM8k79uSwQC7rh3rH/MFaN1IESQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ redux "^4.0.0"
+
"@types/react-router-dom@^4.3.1":
version "4.3.1"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.1.tgz#71fe2918f8f60474a891520def40a63997dafe04"
@@ -1633,6 +1708,11 @@ csstype@^2.2.0:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.3.tgz#b701e5968245bf9b08d54ac83d00b624e622a9fa"
integrity sha512-rINUZXOkcBmoHWEyu7JdHu5JMzkGRoMX4ov9830WNgxf5UYxcBUO0QTKAqeJ5EZfSdlrcJYkC8WwfVW7JYi4yg==
+curriable@^1.2.4:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/curriable/-/curriable-1.2.5.tgz#fb6ff7ad8740927ea09db15d395d9d26ca9d2726"
+ integrity sha512-hQwrkCn8DNiCw5CG8OS0td2wfpCDtxo1dmrVYxCDWUBHQPkpAvN9RqBVbmC64oSQaBqPQD2SOCXcTWH1zXe2mA==
+
cyclist@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
@@ -1768,6 +1848,15 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
+deox@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/deox/-/deox-1.4.0.tgz#7511c082cbe80ffee4c5095aa7efe0138d6057c4"
+ integrity sha512-J9lQse+5LG2/q4hZsjn5Jun2yJP2Al0OfAECQ1KtMXSh5eJYSRn6bh9XBTiBxxi4qymAb/ovC3HPdK760z4OAQ==
+ dependencies:
+ redux-starter-kit "0.4.3"
+ rxjs "^6.3.3"
+ tslib "^1.9.3"
+
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@@ -2280,6 +2369,11 @@ fast-deep-equal@^2.0.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+fast-equals@^1.2.1:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-1.6.2.tgz#f1762bde0d571b5e9d4e1c4ae0599792f6a6df5f"
+ integrity sha512-6FiKwHkrHIqdvo9I92yzCR/zuWE6iy5ldcOszStPbmo7Zzj3OoVeng++GE//JqO4i6JQ4vH/BVAfCmUCki+C3g==
+
fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
@@ -2752,7 +2846,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.1.0:
+hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
@@ -2882,6 +2976,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
dependencies:
safer-buffer ">= 2.1.2 < 3"
+identitate@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/identitate/-/identitate-1.0.1.tgz#4b8bed39454f1d7a476e60ff0e4f82a094841dfc"
+ integrity sha512-xnDJ0JYhiZjBDuJRKbHoVzj5yP9FhATxLyUYswQyPdnJrwzGVBqS6DOmvKJi1lk7P+4dkL+hhUhuOZIcOUtG5A==
+ dependencies:
+ pathington "^1.0.1"
+
ieee754@^1.1.4:
version "1.1.12"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
@@ -2899,6 +3000,11 @@ ignore-walk@^3.0.1:
dependencies:
minimatch "^3.0.4"
+immer@^1.10.5:
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-1.12.1.tgz#40c6e5b292c00560836c2993bda3a24379d466f5"
+ integrity sha512-3fmKM6ovaqDt0CdC9daXpNi5x/YCYS3i4cwLdTVkhJdk5jrDXoPs7lCm3IqM3yhfSnz4tjjxbRG2CziQ7m8ztg==
+
import-fresh@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546"
@@ -2958,7 +3064,7 @@ interpret@^1.1.0:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
-invariant@^2.2.4:
+invariant@^2.1.0, invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
@@ -3766,7 +3872,7 @@ json-schema@0.2.3:
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-json-stringify-safe@~5.0.1:
+json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
@@ -4891,6 +4997,11 @@ path-type@^3.0.0:
dependencies:
pify "^3.0.0"
+pathington@^1.0.1, pathington@^1.1.5:
+ version "1.1.7"
+ resolved "https://registry.yarnpkg.com/pathington/-/pathington-1.1.7.tgz#caf2d2db899a31fea4e81e3657af6acde5171903"
+ integrity sha512-JxzhUzagDfNIOm4qqwQqP3rWeo7rNNOfIahy4n+3GTEdwXLqw5cJHUR0soSopQtNEv763lzxb6eA2xBllpR8zw==
+
pbkdf2@^3.0.3:
version "3.0.17"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6"
@@ -5204,6 +5315,23 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2"
integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA==
+react-is@^16.8.6:
+ version "16.8.6"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
+ integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
+
+react-redux@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.0.2.tgz#34b280a3482aaf60e7d4a504b1295165cbe6b86a"
+ integrity sha512-uKRuMgQt8dWbcz0U75oFK5tDo3boyAKrqvf/j94vpqRFFZfyDDy4kofUgloFIGyuKTq2Zz51zgK9RzOTFXk5ew==
+ dependencies:
+ "@babel/runtime" "^7.4.3"
+ hoist-non-react-statics "^3.3.0"
+ invariant "^2.2.4"
+ loose-envify "^1.4.0"
+ prop-types "^15.7.2"
+ react-is "^16.8.6"
+
react-router-dom@^4.3.1:
version "4.4.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.4.0.tgz#fad67b46375f7081a76d1c92a83a92d28b5abc35"
@@ -5318,6 +5446,56 @@ realpath-native@^1.1.0:
dependencies:
util.promisify "^1.0.0"
+redux-devtools-extension@^2.13.7:
+ version "2.13.8"
+ resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1"
+ integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==
+
+redux-immutable-state-invariant@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/redux-immutable-state-invariant/-/redux-immutable-state-invariant-2.1.0.tgz#308fd3cc7415a0e7f11f51ec997b6379c7055ce1"
+ integrity sha512-3czbDKs35FwiBRsx/3KabUk5zSOoTXC+cgVofGkpBNv3jQcqIe5JrHcF5AmVt7B/4hyJ8MijBIpCJ8cife6yJg==
+ dependencies:
+ invariant "^2.1.0"
+ json-stringify-safe "^5.0.1"
+
+redux-react-hook@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/redux-react-hook/-/redux-react-hook-3.3.1.tgz#3fc91c0def8a49b873c92879843b3f76c8ae7cf4"
+ integrity sha512-a5RHGYT2ZV8Zo1ATP2ubxQGm0fPwn62loSieTeCL7PRgGfdTi8jR0S1K+1/1b4P6RSnEXvs5qC9IVlh2clPbxg==
+
+redux-saga@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.0.2.tgz#0599703f975438f1b2f9d2b9a965ec58f0fdfcd7"
+ integrity sha512-dHV256by3eF2AnBPx1l3HqazQFkErZ82HDXgh4jSRpT72OrX31wyg8DA1q8+0HvENRfJAyhT/4qT5yH/vVqFfw==
+ dependencies:
+ "@redux-saga/core" "^1.0.2"
+
+redux-starter-kit@0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/redux-starter-kit/-/redux-starter-kit-0.4.3.tgz#66a583cde1f1995ae59782d87cc462260ca85fa8"
+ integrity sha512-T3HXtwEGyFLCy63QlZEM95rDzTQ5BKbBhhTINNVFD1yWgHBKtgN3tXw4/sX9+Ve1Y8mAtXbAhep/E7I0YVvZPg==
+ dependencies:
+ immer "^1.10.5"
+ redux "^4.0.0"
+ redux-devtools-extension "^2.13.7"
+ redux-immutable-state-invariant "^2.1.0"
+ redux-thunk "^2.2.0"
+ selectorator "^4.0.1"
+
+redux-thunk@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
+ integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==
+
+"redux@>=0.10 <5", redux@^4.0.0, redux@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5"
+ integrity sha512-R7bAtSkk7nY6O/OYMVR9RiBI+XghjF9rlbl5806HJbQph0LJVHZrU5oaO4q70eUKiqMRqm4y07KLTlMZ2BlVmg==
+ dependencies:
+ loose-envify "^1.4.0"
+ symbol-observable "^1.2.0"
+
reflect-metadata@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
@@ -5328,6 +5506,11 @@ regenerator-runtime@^0.12.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
+regenerator-runtime@^0.13.2:
+ version "0.13.2"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
+ integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==
+
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
@@ -5419,6 +5602,11 @@ require-main-filename@^1.0.1:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
+reselect@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
+ integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
+
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -5575,6 +5763,16 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
+selectorator@^4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/selectorator/-/selectorator-4.0.3.tgz#d33b11027da7e6838de277cd6eb1134125aa788b"
+ integrity sha512-A8+paRhzTab4Qm/38RAVnCgEZFbpn5xIWLyTCDqvyU3Obhmo94RS6UK1H00bVH7+U609sOhqbFJha09POsWURA==
+ dependencies:
+ fast-equals "^1.2.1"
+ identitate "^1.0.0"
+ reselect "^4.0.0"
+ unchanged "^2.0.1"
+
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
@@ -6025,7 +6223,7 @@ supports-color@^6.0.0, supports-color@^6.1.0:
dependencies:
has-flag "^3.0.0"
-symbol-observable@^1.1.0:
+symbol-observable@^1.1.0, symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
@@ -6230,7 +6428,7 @@ tslib@1.9.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8"
integrity sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ==
-tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0:
+tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
@@ -6363,6 +6561,25 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+typescript-compare@^0.0.2:
+ version "0.0.2"
+ resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425"
+ integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA==
+ dependencies:
+ typescript-logic "^0.0.0"
+
+typescript-logic@^0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196"
+ integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q==
+
+typescript-tuple@^2.1.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2"
+ integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q==
+ dependencies:
+ typescript-compare "^0.0.2"
+
typescript@^3.3.3333:
version "3.3.3333"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6"
@@ -6381,6 +6598,14 @@ uglify-js@3.4.x, uglify-js@^3.1.4:
commander "~2.19.0"
source-map "~0.6.1"
+unchanged@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unchanged/-/unchanged-2.1.0.tgz#16308dde5bec15925032d91651f5c3843b957de6"
+ integrity sha512-CYVU0Mz35N821Pjxf+iG6JMPx/Yb6wStUq8uuhR52/+AU3vMiueOTrJ6u1vBKYSke7a75FAi2/jCdQkXcHaNGQ==
+ dependencies:
+ curriable "^1.2.4"
+ pathington "^1.1.5"
+
union-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"