This commit is contained in:
Nathan Bierema 2020-09-12 23:36:54 -04:00
parent 407a5bac43
commit 463e4db8df
14 changed files with 416 additions and 237 deletions

View File

@ -2,10 +2,10 @@ import React from 'react';
import { connect } from 'react-redux';
import { createDevTools } from 'redux-devtools';
import DockMonitor from 'redux-devtools-dock-monitor';
import { Location } from 'history';
import DevtoolsInspector from '../../../src/DevtoolsInspector';
import getOptions from './getOptions';
import { base16Themes } from '../../../src/utils/createStylingFromTheme';
import { Location } from 'history';
import { DemoAppState } from './reducers';
const CustomComponent = () => (

View File

@ -194,7 +194,7 @@ const createRootReducer = (
): Reducer<DemoAppState, DemoAppAction> =>
combineReducers<DemoAppState, DemoAppAction>({
router: connectRouter(history) as Reducer<RouterState, DemoAppAction>,
timeoutUpdateEnabled: (state = false, action: DemoAppAction) =>
timeoutUpdateEnabled: (state = false, action) =>
action.type === 'TOGGLE_TIMEOUT_UPDATE'
? action.timeoutUpdateEnabled
: state,
@ -207,7 +207,7 @@ const createRootReducer = (
// noop
}
) => state,
array: (state = [], action: DemoAppAction) =>
array: (state = [], action) =>
action.type === 'PUSH'
? [...state, Math.random()]
: action.type === 'POP'
@ -215,13 +215,13 @@ const createRootReducer = (
: action.type === 'REPLACE'
? [Math.random(), ...state.slice(1)]
: state,
hugeArrays: (state = [], action: DemoAppAction) =>
hugeArrays: (state = [], action) =>
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
hugeObjects: (state = [], action: DemoAppAction) =>
hugeObjects: (state = [], action) =>
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
iterators: (state = [], action: DemoAppAction) =>
iterators: (state = [], action) =>
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
nested: (state = NESTED, action: DemoAppAction) =>
nested: (state = NESTED, action) =>
action.type === 'CHANGE_NESTED'
? {
...state,
@ -238,29 +238,26 @@ const createRootReducer = (
},
}
: state,
recursive: (state: { obj?: unknown }[] = [], action: DemoAppAction) =>
recursive: (state: { obj?: unknown }[] = [], action) =>
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
immutables: (
state: Immutable.Map<string, unknown>[] = [],
action: DemoAppAction
) =>
immutables: (state: Immutable.Map<string, unknown>[] = [], action) =>
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
maps: (state: Map<string, MapValue>[] = [], action: DemoAppAction) =>
maps: (state: Map<string, MapValue>[] = [], action) =>
action.type === 'ADD_NATIVE_MAP' ? [...state, NATIVE_MAP] : state,
immutableNested: (state = IMMUTABLE_NESTED, action: DemoAppAction) =>
immutableNested: (state = IMMUTABLE_NESTED, action) =>
action.type === 'CHANGE_IMMUTABLE_NESTED'
? state.updateIn(
['long', 'nested', 0, 'path', 'to', 'a'],
(str: string) => str + '!'
)
: state,
addFunction: (state = null, action: DemoAppAction) =>
addFunction: (state = null, action) =>
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
addSymbol: (state = null, action: DemoAppAction) =>
addSymbol: (state = null, action) =>
action.type === 'ADD_SYMBOL'
? { s: window.Symbol('symbol'), error: new Error('TEST') }
: state,
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action: DemoAppAction) =>
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
});

View File

@ -1,4 +1,5 @@
import DevtoolsInspector from './DevtoolsInspector';
export default DevtoolsInspector;
export { TabComponentProps } from './ActionPreview';
export { Tab, TabComponentProps } from './ActionPreview';
export { DevtoolsInspectorState } from './redux';
export { base16Themes } from './utils/createStylingFromTheme';

View File

@ -1,4 +1,7 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"resolveJsonModule": true
},
"include": ["webpack.config.ts"]
}

View File

@ -1,14 +1,14 @@
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const pkg = require('./package.json');
import * as path from 'path';
import * as webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
import pkg from '../../package.json';
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
devtool: 'eval-source-map',
mode: process.env.NODE_ENV || 'development',
entry: isProduction
? ['./demo/src/js/index']
: [
@ -20,39 +20,14 @@ module.exports = {
path: path.join(__dirname, 'demo/dist'),
filename: 'js/bundle.js',
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
inject: true,
template: 'demo/src/index.html',
package: pkg,
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
},
}),
].concat(
isProduction
? [
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
output: { comments: false },
}),
]
: [new webpack.HotModuleReplacementPlugin()]
),
resolve: {
extensions: ['.js', '.jsx'],
},
module: {
rules: [
{
test: /\.jsx?$/,
test: /\.(js|ts)x?$/,
loader: 'babel-loader',
include: [
path.join(__dirname, 'src'),
path.join(__dirname, 'demo/src/js'),
path.join(__dirname, '../../src'),
path.join(__dirname, '../src/js'),
],
},
{
@ -66,6 +41,22 @@ module.exports = {
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
inject: true,
template: 'demo/src/index.html',
package: pkg,
}),
new ForkTsCheckerWebpackPlugin({
typescript: {
configFile: 'demo/tsconfig.json',
},
}),
].concat(isProduction ? [] : [new webpack.HotModuleReplacementPlugin()]),
devServer: isProduction
? null
: {
@ -78,4 +69,5 @@ module.exports = {
},
historyApiFallback: true,
},
devtool: 'eval-source-map',
};

View File

@ -1,11 +1,35 @@
import React from 'react';
import React, { CSSProperties } from 'react';
import { connect } from 'react-redux';
import pkg from '../../../package.json';
import { Button, Toolbar, Spacer } from 'devui';
import getOptions from './getOptions';
import { push as pushRoute } from 'connected-react-router';
import pkg from '../../../package.json';
import getOptions from './getOptions';
import { DemoAppState } from './reducers';
import {
AddFunctionAction,
AddHugeObjectAction,
AddImmutableMapAction,
AddIteratorAction,
AddRecursiveAction,
AddSymbolAction,
ChangeImmutableNestedAction,
ChangeNestedAction,
HugePayloadAction,
IncrementAction,
PopAction,
PushAction,
PushHugeArrayAction,
ReplaceAction,
ShuffleArrayAction,
TimeoutUpdateAction,
ToggleTimeoutUpdateAction,
} from './reducers';
const styles = {
const styles: {
wrapper: CSSProperties;
muted: CSSProperties;
link: CSSProperties;
} = {
wrapper: {
height: '100vh',
width: '450px',
@ -24,7 +48,30 @@ const styles = {
const ROOT = '/'; // process.env.NODE_ENV === 'production' ? '/' : '/';
class DemoApp extends React.Component {
interface Props
extends Omit<DemoAppState, 'addFunction' | 'addSymbol' | 'shuffleArray'> {
toggleTimeoutUpdate: (timeoutUpdateEnabled: boolean) => void;
timeoutUpdate: () => void;
increment: () => void;
push: () => void;
pop: () => void;
replace: () => void;
changeNested: () => void;
pushHugeArray: () => void;
addIterator: () => void;
addHugeObject: () => void;
addRecursive: () => void;
addImmutableMap: () => void;
changeImmutableNested: () => void;
hugePayload: () => void;
addFunction: () => void;
addSymbol: () => void;
shuffleArray: () => void;
}
class DemoApp extends React.Component<Props> {
timeout?: number;
render() {
const options = getOptions(this.props.router.location);
@ -48,7 +95,7 @@ class DemoApp extends React.Component {
<Toolbar>
<Spacer />
<Button onClick={this.props.pushHugeArray}>Push Huge Array</Button>
<Button onClick={this.props.addHugeObect}>Add Huge Object</Button>
<Button onClick={this.props.addHugeObject}>Add Huge Object</Button>
<Button onClick={this.props.hugePayload}>Huge Payload</Button>
<Spacer />
</Toolbar>
@ -98,36 +145,40 @@ class DemoApp extends React.Component {
this.props.toggleTimeoutUpdate(enabled);
if (enabled) {
this.timeout = setInterval(this.props.timeoutUpdate, 1000);
this.timeout = window.setInterval(this.props.timeoutUpdate, 1000);
} else {
clearTimeout(this.timeout);
}
};
}
export default connect((state) => state, {
toggleTimeoutUpdate: (timeoutUpdateEnabled) => ({
export default connect((state: DemoAppState) => state, {
toggleTimeoutUpdate: (
timeoutUpdateEnabled: boolean
): ToggleTimeoutUpdateAction => ({
type: 'TOGGLE_TIMEOUT_UPDATE',
timeoutUpdateEnabled,
}),
timeoutUpdate: () => ({ type: 'TIMEOUT_UPDATE' }),
increment: () => ({ type: 'INCREMENT' }),
push: () => ({ type: 'PUSH' }),
pop: () => ({ type: 'POP' }),
replace: () => ({ type: 'REPLACE' }),
changeNested: () => ({ type: 'CHANGE_NESTED' }),
pushHugeArray: () => ({ type: 'PUSH_HUGE_ARRAY' }),
addIterator: () => ({ type: 'ADD_ITERATOR' }),
addHugeObect: () => ({ type: 'ADD_HUGE_OBJECT' }),
addRecursive: () => ({ type: 'ADD_RECURSIVE' }),
addImmutableMap: () => ({ type: 'ADD_IMMUTABLE_MAP' }),
changeImmutableNested: () => ({ type: 'CHANGE_IMMUTABLE_NESTED' }),
hugePayload: () => ({
timeoutUpdate: (): TimeoutUpdateAction => ({ type: 'TIMEOUT_UPDATE' }),
increment: (): IncrementAction => ({ type: 'INCREMENT' }),
push: (): PushAction => ({ type: 'PUSH' }),
pop: (): PopAction => ({ type: 'POP' }),
replace: (): ReplaceAction => ({ type: 'REPLACE' }),
changeNested: (): ChangeNestedAction => ({ type: 'CHANGE_NESTED' }),
pushHugeArray: (): PushHugeArrayAction => ({ type: 'PUSH_HUGE_ARRAY' }),
addIterator: (): AddIteratorAction => ({ type: 'ADD_ITERATOR' }),
addHugeObject: (): AddHugeObjectAction => ({ type: 'ADD_HUGE_OBJECT' }),
addRecursive: (): AddRecursiveAction => ({ type: 'ADD_RECURSIVE' }),
addImmutableMap: (): AddImmutableMapAction => ({ type: 'ADD_IMMUTABLE_MAP' }),
changeImmutableNested: (): ChangeImmutableNestedAction => ({
type: 'CHANGE_IMMUTABLE_NESTED',
}),
hugePayload: (): HugePayloadAction => ({
type: 'HUGE_PAYLOAD',
payload: Array.from({ length: 10000 }).map((_, i) => i),
}),
addFunction: () => ({ type: 'ADD_FUNCTION' }),
addSymbol: () => ({ type: 'ADD_SYMBOL' }),
shuffleArray: () => ({ type: 'SHUFFLE_ARRAY' }),
addFunction: (): AddFunctionAction => ({ type: 'ADD_FUNCTION' }),
addSymbol: (): AddSymbolAction => ({ type: 'ADD_SYMBOL' }),
shuffleArray: (): ShuffleArrayAction => ({ type: 'SHUFFLE_ARRAY' }),
pushRoute,
})(DemoApp);

View File

@ -1,12 +1,18 @@
import React from 'react';
import { connect } from 'react-redux';
import { createDevTools } from 'redux-devtools';
import InspectorMonitor from 'redux-devtools-inspector-monitor';
import InspectorMonitor, {
base16Themes,
Tab,
} from 'redux-devtools-inspector-monitor';
import DockMonitor from 'redux-devtools-dock-monitor';
import { Location } from 'history';
import getOptions from './getOptions';
import TestGenerator from '../../../src';
import { DemoAppState } from './reducers';
import { Action } from 'redux';
export const getDevTools = (location) =>
export const getDevTools = (location: { search: string }) =>
createDevTools(
<DockMonitor
defaultIsVisible
@ -15,27 +21,28 @@ export const getDevTools = (location) =>
changeMonitorKey="ctrl-m"
>
<InspectorMonitor
theme={getOptions(location).theme}
shouldPersistState
theme={getOptions(location).theme as keyof typeof base16Themes}
invertTheme={!getOptions(location).dark}
supportImmutable={getOptions(location).supportImmutable}
tabs={(defaultTabs) => [
{
name: 'Test',
component: TestGenerator,
},
...defaultTabs,
]}
tabs={(defaultTabs) =>
[
{
name: 'Test',
component: TestGenerator,
},
...defaultTabs,
] as Tab<unknown, Action<unknown>>[]
}
/>
</DockMonitor>
);
const UnconnectedDevTools = ({ location }) => {
const UnconnectedDevTools = ({ location }: { location: Location }) => {
const DevTools = getDevTools(location);
return <DevTools />;
};
const mapStateToProps = (state) => ({
const mapStateToProps = (state: DemoAppState) => ({
location: state.router.location,
});

View File

@ -1,11 +0,0 @@
export default function getOptions(location) {
return {
useExtension: location.search.indexOf('ext') !== -1,
supportImmutable: location.search.indexOf('immutable') !== -1,
theme: do {
const match = location.search.match(/theme=([^&]+)/);
match ? match[1] : 'inspector';
},
dark: location.search.indexOf('dark') !== -1,
};
}

View File

@ -0,0 +1,20 @@
export interface Options {
useExtension: boolean;
supportImmutable: boolean;
theme: string;
dark: boolean;
}
export default function getOptions(location: { search: string }) {
return {
useExtension: location.search.indexOf('ext') !== -1,
supportImmutable: location.search.indexOf('immutable') !== -1,
theme: getTheme(),
dark: location.search.indexOf('dark') !== -1,
};
}
function getTheme() {
const match = /theme=([^&]+)/.exec(location.search);
return match ? match[1] : 'inspector';
}

View File

@ -2,20 +2,26 @@ import 'devui/lib/presets';
import React from 'react';
import { render } from 'react-dom';
import { Container } from 'devui';
import DemoApp from './DemoApp';
import { Provider } from 'react-redux';
import createRootReducer from './reducers';
import { createStore, applyMiddleware, compose } from 'redux';
import {
createStore,
applyMiddleware,
compose,
StoreEnhancer,
StoreEnhancerStoreCreator,
} from 'redux';
import logger from 'redux-logger';
import { Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { ConnectedRouter, routerMiddleware } from 'connected-react-router';
import { persistState } from 'redux-devtools';
import DemoApp from './DemoApp';
import createRootReducer from './reducers';
import getOptions from './getOptions';
import { ConnectedDevTools, getDevTools } from './DevTools';
function getDebugSessionKey() {
const matches = window.location.href.match(/[?&]debug_session=([^&#]+)\b/);
const matches = /[?&]debug_session=([^&#]+)\b/.exec(window.location.href);
return matches && matches.length > 0 ? matches[1] : null;
}
@ -29,21 +35,23 @@ const DevTools = getDevTools(window.location);
const history = createBrowserHistory();
const useDevtoolsExtension =
!!window.__REDUX_DEVTOOLS_EXTENSION__ &&
!!((window as unknown) as { __REDUX_DEVTOOLS_EXTENSION__: unknown }) &&
getOptions(window.location).useExtension;
const enhancer = compose(
applyMiddleware(logger, routerMiddleware(history)),
(...args) => {
(next: StoreEnhancerStoreCreator) => {
const instrument = useDevtoolsExtension
? window.__REDUX_DEVTOOLS_EXTENSION__()
? ((window as unknown) as {
__REDUX_DEVTOOLS_EXTENSION__(): StoreEnhancer;
}).__REDUX_DEVTOOLS_EXTENSION__()
: DevTools.instrument();
return instrument(...args);
return instrument(next);
},
persistState(getDebugSessionKey())
);
const store = createStore(createRootReducer(history), {}, enhancer);
const store = createStore(createRootReducer(history), enhancer);
render(
<Provider store={store}>

View File

@ -1,125 +0,0 @@
import Immutable from 'immutable';
import shuffle from 'lodash.shuffle';
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
const NESTED = {
long: {
nested: [
{
path: {
to: {
a: 'key',
},
},
},
],
},
};
const IMMUTABLE_NESTED = Immutable.fromJS(NESTED);
/* eslint-disable babel/new-cap */
const IMMUTABLE_MAP = Immutable.Map({
map: Immutable.Map({ a: 1, b: 2, c: 3 }),
list: Immutable.List(['a', 'b', 'c']),
set: Immutable.Set(['a', 'b', 'c']),
stack: Immutable.Stack(['a', 'b', 'c']),
seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]),
});
/* eslint-enable babel/new-cap */
const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({
str: 'key ' + key,
}));
const HUGE_OBJECT = Array.from({ length: 5000 }).reduce(
(o, _, key) => ((o['key ' + key] = 'item ' + key), o),
{}
);
const FUNC = function (a, b, c) {
return a + b + c;
};
const RECURSIVE = {};
RECURSIVE.obj = RECURSIVE;
function createIterator() {
const iterable = {};
iterable[window.Symbol.iterator] = function* iterator() {
for (var i = 0; i < 333; i++) {
yield 'item ' + i;
}
};
return iterable;
}
const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string'];
const createRootReducer = (history) =>
combineReducers({
router: connectRouter(history),
timeoutUpdateEnabled: (state = false, action) =>
action.type === 'TOGGLE_TIMEOUT_UPDATE'
? action.timeoutUpdateEnabled
: state,
store: (state = 0, action) =>
action.type === 'INCREMENT' ? state + 1 : state,
undefined: (state = { val: undefined }) => state,
null: (state = null) => state,
func: (state = () => {}) => state,
array: (state = [], action) =>
action.type === 'PUSH'
? [...state, Math.random()]
: action.type === 'POP'
? state.slice(0, state.length - 1)
: action.type === 'REPLACE'
? [Math.random(), ...state.slice(1)]
: state,
hugeArrays: (state = [], action) =>
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
hugeObjects: (state = [], action) =>
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
iterators: (state = [], action) =>
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
nested: (state = NESTED, action) =>
action.type === 'CHANGE_NESTED'
? {
...state,
long: {
nested: [
{
path: {
to: {
a: state.long.nested[0].path.to.a + '!',
},
},
},
],
},
}
: state,
recursive: (state = [], action) =>
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
immutables: (state = [], action) =>
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
immutableNested: (state = IMMUTABLE_NESTED, action) =>
action.type === 'CHANGE_IMMUTABLE_NESTED'
? state.updateIn(
['long', 'nested', 0, 'path', 'to', 'a'],
(str) => str + '!'
)
: state,
addFunction: (state = null, action) =>
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
addSymbol: (state = null, action) =>
action.type === 'ADD_SYMBOL' ? { s: window.Symbol('symbol') } : state,
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
});
export default createRootReducer;

View File

@ -0,0 +1,232 @@
import Immutable from 'immutable';
import shuffle from 'lodash.shuffle';
import { combineReducers, Reducer } from 'redux';
import {
connectRouter,
LocationChangeAction,
RouterState,
} from 'connected-react-router';
import { History } from 'history';
type Nested = { long: { nested: { path: { to: { a: string } } }[] } };
const NESTED = {
long: {
nested: [
{
path: {
to: {
a: 'key',
},
},
},
],
},
};
const IMMUTABLE_NESTED = Immutable.fromJS(NESTED);
const IMMUTABLE_MAP = Immutable.Map({
map: Immutable.Map({ a: 1, b: 2, c: 3 }),
list: Immutable.List(['a', 'b', 'c']),
set: Immutable.Set(['a', 'b', 'c']),
stack: Immutable.Stack(['a', 'b', 'c']),
seq: Immutable.Seq([1, 2, 3, 4, 5, 6, 7, 8]),
});
const HUGE_ARRAY = Array.from({ length: 5000 }).map((_, key) => ({
str: `key ${key}`,
}));
const HUGE_OBJECT = Array.from({ length: 5000 }).reduce(
(o: { [key: string]: string }, _, key) => (
(o[`key ${key}`] = `item ${key}`), o
),
{}
);
const FUNC = function (a: number, b: number, c: number) {
return a + b + c;
};
const RECURSIVE: { obj?: unknown } = {};
RECURSIVE.obj = RECURSIVE;
function createIterator() {
const iterable: { [Symbol.iterator](): IterableIterator<string> } = {
[Symbol.iterator]: function* iterator() {
for (let i = 0; i < 333; i++) {
yield `item ${i}`;
}
},
};
return iterable;
}
const DEFAULT_SHUFFLE_ARRAY = [0, 1, null, { id: 1 }, { id: 2 }, 'string'];
export interface ToggleTimeoutUpdateAction {
type: 'TOGGLE_TIMEOUT_UPDATE';
timeoutUpdateEnabled: boolean;
}
export interface TimeoutUpdateAction {
type: 'TIMEOUT_UPDATE';
}
export interface IncrementAction {
type: 'INCREMENT';
}
export interface PushAction {
type: 'PUSH';
}
export interface PopAction {
type: 'POP';
}
export interface ReplaceAction {
type: 'REPLACE';
}
export interface ChangeNestedAction {
type: 'CHANGE_NESTED';
}
export interface PushHugeArrayAction {
type: 'PUSH_HUGE_ARRAY';
}
export interface AddIteratorAction {
type: 'ADD_ITERATOR';
}
export interface AddHugeObjectAction {
type: 'ADD_HUGE_OBJECT';
}
export interface AddRecursiveAction {
type: 'ADD_RECURSIVE';
}
export interface AddImmutableMapAction {
type: 'ADD_IMMUTABLE_MAP';
}
export interface ChangeImmutableNestedAction {
type: 'CHANGE_IMMUTABLE_NESTED';
}
export interface HugePayloadAction {
type: 'HUGE_PAYLOAD';
payload: number[];
}
export interface AddFunctionAction {
type: 'ADD_FUNCTION';
}
export interface AddSymbolAction {
type: 'ADD_SYMBOL';
}
export interface ShuffleArrayAction {
type: 'SHUFFLE_ARRAY';
}
type DemoAppAction =
| ToggleTimeoutUpdateAction
| TimeoutUpdateAction
| IncrementAction
| PushAction
| PopAction
| ReplaceAction
| ChangeNestedAction
| PushHugeArrayAction
| AddIteratorAction
| AddHugeObjectAction
| AddRecursiveAction
| AddImmutableMapAction
| ChangeImmutableNestedAction
| HugePayloadAction
| AddFunctionAction
| AddSymbolAction
| ShuffleArrayAction
| LocationChangeAction;
export interface DemoAppState {
router: RouterState;
timeoutUpdateEnabled: boolean;
store: number;
undefined: { val: undefined };
null: null;
func: () => void;
array: number[];
hugeArrays: { str: string }[];
hugeObjects: { [key: string]: string }[];
iterators: { [Symbol.iterator](): IterableIterator<string> }[];
nested: Nested;
recursive: { obj?: unknown }[];
immutables: Immutable.Map<string, unknown>[];
immutableNested: Immutable.Map<unknown, unknown>;
addFunction: { f: (a: number, b: number, c: number) => number } | null;
addSymbol: { s: symbol; error: Error } | null;
shuffleArray: unknown[];
}
const createRootReducer = (
history: History
): Reducer<DemoAppState, DemoAppAction> =>
combineReducers<DemoAppState, DemoAppAction>({
router: connectRouter(history) as Reducer<RouterState, DemoAppAction>,
timeoutUpdateEnabled: (state = false, action) =>
action.type === 'TOGGLE_TIMEOUT_UPDATE'
? action.timeoutUpdateEnabled
: state,
store: (state = 0, action) =>
action.type === 'INCREMENT' ? state + 1 : state,
undefined: (state = { val: undefined }) => state,
null: (state = null) => state,
func: (
state = () => {
// noop
}
) => state,
array: (state = [], action) =>
action.type === 'PUSH'
? [...state, Math.random()]
: action.type === 'POP'
? state.slice(0, state.length - 1)
: action.type === 'REPLACE'
? [Math.random(), ...state.slice(1)]
: state,
hugeArrays: (state = [], action) =>
action.type === 'PUSH_HUGE_ARRAY' ? [...state, ...HUGE_ARRAY] : state,
hugeObjects: (state = [], action) =>
action.type === 'ADD_HUGE_OBJECT' ? [...state, HUGE_OBJECT] : state,
iterators: (state = [], action) =>
action.type === 'ADD_ITERATOR' ? [...state, createIterator()] : state,
nested: (state = NESTED, action) =>
action.type === 'CHANGE_NESTED'
? {
...state,
long: {
nested: [
{
path: {
to: {
a: state.long.nested[0].path.to.a + '!',
},
},
},
],
},
}
: state,
recursive: (state = [], action) =>
action.type === 'ADD_RECURSIVE' ? [...state, { ...RECURSIVE }] : state,
immutables: (state = [], action) =>
action.type === 'ADD_IMMUTABLE_MAP' ? [...state, IMMUTABLE_MAP] : state,
immutableNested: (state = IMMUTABLE_NESTED, action) =>
action.type === 'CHANGE_IMMUTABLE_NESTED'
? state.updateIn(
['long', 'nested', 0, 'path', 'to', 'a'],
(str: string) => str + '!'
)
: state,
addFunction: (state = null, action) =>
action.type === 'ADD_FUNCTION' ? { f: FUNC } : state,
addSymbol: (state = null, action) =>
action.type === 'ADD_SYMBOL'
? { s: window.Symbol('symbol'), error: new Error('TEST') }
: state,
shuffleArray: (state = DEFAULT_SHUFFLE_ARRAY, action) =>
action.type === 'SHUFFLE_ARRAY' ? shuffle(state) : state,
});
export default createRootReducer;

View File

@ -1,4 +1,7 @@
{
"extends": "../../../tsconfig.react.base.json",
"compilerOptions": {
"resolveJsonModule": true
},
"include": ["../src", "src"]
}

View File

@ -1,7 +1,8 @@
{
"extends": "../../tsconfig.react.base.json",
"compilerOptions": {
"outDir": "lib"
"outDir": "lib",
"resolveJsonModule": true
},
"include": ["src"]
}