From f0fecd20f352a1dfeb047f90c99b04033e1d0178 Mon Sep 17 00:00:00 2001 From: daishi Date: Sat, 25 May 2019 21:53:37 +0900 Subject: [PATCH 01/21] squash be7e8cd86bbb65060caadbcdd3debc65bcea6073 --- frameworks/keyed/react-hooks/package.json | 4 +- frameworks/keyed/react-redux-hooks/index.html | 12 ++ .../keyed/react-redux-hooks/package.json | 40 +++++ .../keyed/react-redux-hooks/src/main.jsx | 158 ++++++++++++++++++ .../keyed/react-redux-hooks/webpack.config.js | 78 +++++++++ frameworks/keyed/react-redux/package.json | 2 +- .../keyed/reactive-react-redux/index.html | 12 ++ .../keyed/reactive-react-redux/package.json | 40 +++++ .../keyed/reactive-react-redux/src/main.jsx | 156 +++++++++++++++++ .../reactive-react-redux/webpack.config.js | 78 +++++++++ 10 files changed, 577 insertions(+), 3 deletions(-) create mode 100755 frameworks/keyed/react-redux-hooks/index.html create mode 100644 frameworks/keyed/react-redux-hooks/package.json create mode 100755 frameworks/keyed/react-redux-hooks/src/main.jsx create mode 100755 frameworks/keyed/react-redux-hooks/webpack.config.js create mode 100755 frameworks/keyed/reactive-react-redux/index.html create mode 100644 frameworks/keyed/reactive-react-redux/package.json create mode 100755 frameworks/keyed/reactive-react-redux/src/main.jsx create mode 100755 frameworks/keyed/reactive-react-redux/webpack.config.js diff --git a/frameworks/keyed/react-hooks/package.json b/frameworks/keyed/react-hooks/package.json index 7b3d42294..693526f3a 100644 --- a/frameworks/keyed/react-hooks/package.json +++ b/frameworks/keyed/react-hooks/package.json @@ -32,7 +32,7 @@ "webpack-cli": "3.2.3" }, "dependencies": { - "react": "16.8.3", - "react-dom": "16.8.3" + "react": "16.8.6", + "react-dom": "16.8.6" } } diff --git a/frameworks/keyed/react-redux-hooks/index.html b/frameworks/keyed/react-redux-hooks/index.html new file mode 100755 index 000000000..bae8383bf --- /dev/null +++ b/frameworks/keyed/react-redux-hooks/index.html @@ -0,0 +1,12 @@ + + + + + React + Redux + hooks + + + +
+ + + diff --git a/frameworks/keyed/react-redux-hooks/package.json b/frameworks/keyed/react-redux-hooks/package.json new file mode 100644 index 000000000..dce7c87dd --- /dev/null +++ b/frameworks/keyed/react-redux-hooks/package.json @@ -0,0 +1,40 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "react-redux": "7.1.0-alpha.5", + "redux": "4.0.1" + } +} diff --git a/frameworks/keyed/react-redux-hooks/src/main.jsx b/frameworks/keyed/react-redux-hooks/src/main.jsx new file mode 100755 index 000000000..7b18b1045 --- /dev/null +++ b/frameworks/keyed/react-redux-hooks/src/main.jsx @@ -0,0 +1,158 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createStore } from 'redux'; +import { Provider, useSelector, useDispatch } from 'react-redux'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const store = createStore((state = { data: [], selected: 0 }, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ i }) => { + const selector = useCallback((state) => { + const item = state.data[i]; + return state.selected === item.id ? { id: item.id, label: item.label, selected: true } : item; + }, [i]); + const { selected, id, label } = useSelector(selector); + const dispatch = useDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const data = useSelector(state => state.data); + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

React + Redux + hooks

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/react-redux-hooks/webpack.config.js b/frameworks/keyed/react-redux-hooks/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/react-redux-hooks/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; diff --git a/frameworks/keyed/react-redux/package.json b/frameworks/keyed/react-redux/package.json index 628ece7db..e446f2bf0 100644 --- a/frameworks/keyed/react-redux/package.json +++ b/frameworks/keyed/react-redux/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.3", "react-dom": "16.8.3", - "react-redux": "6.0.0", + "react-redux": "7.0.3", "redux": "4.0.1" } } diff --git a/frameworks/keyed/reactive-react-redux/index.html b/frameworks/keyed/reactive-react-redux/index.html new file mode 100755 index 000000000..c2ba7599a --- /dev/null +++ b/frameworks/keyed/reactive-react-redux/index.html @@ -0,0 +1,12 @@ + + + + + reactive-react-redux + + + +
+ + + diff --git a/frameworks/keyed/reactive-react-redux/package.json b/frameworks/keyed/reactive-react-redux/package.json new file mode 100644 index 000000000..b6a591880 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux/package.json @@ -0,0 +1,40 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:reactive-react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "reactive-react-redux": "3.0.0", + "redux": "4.0.1" + } +} diff --git a/frameworks/keyed/reactive-react-redux/src/main.jsx b/frameworks/keyed/reactive-react-redux/src/main.jsx new file mode 100755 index 000000000..9dd440656 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux/src/main.jsx @@ -0,0 +1,156 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createStore } from 'redux'; +import { ReduxProvider, useReduxState, useReduxDispatch } from 'reactive-react-redux'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const store = createStore((state = { data: [], selected: 0 }, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ item, selected }) => { + const { id, label } = item; + const dispatch = useReduxDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data, selectedId }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const state = useReduxState(); + const data = state.data; + const selectedId = state.selected; + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useReduxDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

reactive-react-redux

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/reactive-react-redux/webpack.config.js b/frameworks/keyed/reactive-react-redux/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; From 943615feb0adca9590a9ce194e0cd5ead485c588 Mon Sep 17 00:00:00 2001 From: daishi Date: Sat, 25 May 2019 23:16:10 +0900 Subject: [PATCH 02/21] add react-hooks-global-state --- .../keyed/react-hooks-global-state/index.html | 12 ++ .../react-hooks-global-state/package.json | 39 +++++ .../react-hooks-global-state/src/main.jsx | 133 ++++++++++++++++++ .../webpack.config.js | 78 ++++++++++ 4 files changed, 262 insertions(+) create mode 100644 frameworks/keyed/react-hooks-global-state/index.html create mode 100644 frameworks/keyed/react-hooks-global-state/package.json create mode 100644 frameworks/keyed/react-hooks-global-state/src/main.jsx create mode 100644 frameworks/keyed/react-hooks-global-state/webpack.config.js diff --git a/frameworks/keyed/react-hooks-global-state/index.html b/frameworks/keyed/react-hooks-global-state/index.html new file mode 100644 index 000000000..23297f4ec --- /dev/null +++ b/frameworks/keyed/react-hooks-global-state/index.html @@ -0,0 +1,12 @@ + + + + + react-hooks-global-state + + + +
+ + + diff --git a/frameworks/keyed/react-hooks-global-state/package.json b/frameworks/keyed/react-hooks-global-state/package.json new file mode 100644 index 000000000..175ae8042 --- /dev/null +++ b/frameworks/keyed/react-hooks-global-state/package.json @@ -0,0 +1,39 @@ +{ + "name": "js-framework-benchmark-react-hooks", + "version": "1.1.1", + "description": "React Hooks demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:react-hooks-global-state" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.2", + "@babel/preset-env": "7.3.1", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.3.0", + "babel-loader": "8.0.5", + "terser-webpack-plugin": "1.2.2", + "webpack": "4.29.2", + "webpack-cli": "3.2.3" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "react-hooks-global-state": "0.11.0" + } +} diff --git a/frameworks/keyed/react-hooks-global-state/src/main.jsx b/frameworks/keyed/react-hooks-global-state/src/main.jsx new file mode 100644 index 000000000..da23df72c --- /dev/null +++ b/frameworks/keyed/react-hooks-global-state/src/main.jsx @@ -0,0 +1,133 @@ +import React, { memo, useReducer, useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createGlobalState } from 'react-hooks-global-state'; + +function random(max) { return Math.round(Math.random() * 1000) % max; } + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + }; + } + return data; +} + +const { GlobalStateProvider, useGlobalState, setGlobalState } = createGlobalState({ data: [], selected: 0 }); + +function doAction(action) { + switch (action.type) { + case 'RUN': + setGlobalState('data', buildData(1000)); + setGlobalState('selected', 0); + break; + case 'RUN_LOTS': + setGlobalState('data', buildData(10000)); + setGlobalState('selected', 0); + break; + case 'ADD': + setGlobalState('data', data => data.concat(buildData(1000))); + break; + case 'UPDATE': + setGlobalState('data', data => { + const newData = data.slice(0); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return newData; + }); + break; + case 'CLEAR': + setGlobalState('data', []); + setGlobalState('selected', 0); + break; + case 'SWAP_ROWS': + setGlobalState('data', data => [data[0], data[998], ...data.slice(2, 998), data[1], data[999]]); + break; + case 'REMOVE': + setGlobalState('data', data => { + const idx = data.findIndex((d) => d.id === action.id); + return [...data.slice(0, idx), ...data.slice(idx + 1)]; + }); + break; + case 'SELECT': + setGlobalState('selected', action.id); + break; + } +} + +const GlyphIcon = ; + +const Row = memo(({ item }) => { + const [selected] = useGlobalState('selected'); + const select = useCallback(() => doAction({ type: 'SELECT', id: item.id }), []), + remove = useCallback(() => doAction({ type: 'REMOVE', id: item.id }), []); + + return ( + {item.id} + {item.label} + {GlyphIcon} + + ); +}); + +const Button = ({ id, cb, title }) => ( +
+ +
+); + +const Jumbotron = memo(() => ( +
+
+
+

react-hooks-global-state

+
+
+
+
+
+
+
+), () => true); + +const Main = () => { + const [data] = useGlobalState('data'); + + return (
+ + + {data.map(item => ( + + ))} +
+ +
); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById('main') +); diff --git a/frameworks/keyed/react-hooks-global-state/webpack.config.js b/frameworks/keyed/react-hooks-global-state/webpack.config.js new file mode 100644 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/react-hooks-global-state/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; From 79d190d6ac1269b6f2e6bf3a98143e5b1eb9a9d4 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 26 May 2019 00:22:47 +0900 Subject: [PATCH 03/21] change back to react-hooks style --- .../keyed/react-hooks-global-state/src/main.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frameworks/keyed/react-hooks-global-state/src/main.jsx b/frameworks/keyed/react-hooks-global-state/src/main.jsx index da23df72c..a0a629f4c 100644 --- a/frameworks/keyed/react-hooks-global-state/src/main.jsx +++ b/frameworks/keyed/react-hooks-global-state/src/main.jsx @@ -70,12 +70,11 @@ function doAction(action) { const GlyphIcon = ; -const Row = memo(({ item }) => { - const [selected] = useGlobalState('selected'); - const select = useCallback(() => doAction({ type: 'SELECT', id: item.id }), []), - remove = useCallback(() => doAction({ type: 'REMOVE', id: item.id }), []); +const Row = memo(({ item, selected }) => { + const select = useCallback(() => doAction({ type: 'SELECT', id: item.id }), []); + const remove = useCallback(() => doAction({ type: 'REMOVE', id: item.id }), []); - return ( + return ( {item.id} {item.label} {GlyphIcon} @@ -111,12 +110,13 @@ const Jumbotron = memo(() => ( const Main = () => { const [data] = useGlobalState('data'); + const [selected] = useGlobalState('selected'); return (
{data.map(item => ( - + ))}
From e4b85a82c509c4598f506ef6814bfb80c6a4e246 Mon Sep 17 00:00:00 2001 From: daishi Date: Tue, 11 Jun 2019 21:51:38 +0900 Subject: [PATCH 04/21] update redux 7.1.0 --- frameworks/keyed/react-redux-hooks/package.json | 2 +- frameworks/keyed/react-redux/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/keyed/react-redux-hooks/package.json b/frameworks/keyed/react-redux-hooks/package.json index dce7c87dd..a5547a8c1 100644 --- a/frameworks/keyed/react-redux-hooks/package.json +++ b/frameworks/keyed/react-redux-hooks/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-redux": "7.1.0-alpha.5", + "react-redux": "7.1.0", "redux": "4.0.1" } } diff --git a/frameworks/keyed/react-redux/package.json b/frameworks/keyed/react-redux/package.json index e446f2bf0..ae18507a3 100644 --- a/frameworks/keyed/react-redux/package.json +++ b/frameworks/keyed/react-redux/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.3", "react-dom": "16.8.3", - "react-redux": "7.0.3", + "react-redux": "7.1.0", "redux": "4.0.1" } } From 8dd507fa897d3580c16b2df9a71688435efafa2b Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 16 Jun 2019 21:54:39 +0900 Subject: [PATCH 05/21] two reactive-react-redux@next and two react-tracked --- .../react-tracked-useSelector/index.html | 12 ++ .../react-tracked-useSelector/package.json | 39 +++++ .../react-tracked-useSelector/src/main.jsx | 157 +++++++++++++++++ .../webpack.config.js | 0 .../index.html | 0 .../package.json | 39 +++++ .../src/main.jsx | 156 +++++++++++++++++ .../webpack.config.js | 78 +++++++++ .../index.html | 12 ++ .../package.json | 40 +++++ .../src/main.jsx | 158 ++++++++++++++++++ .../webpack.config.js | 78 +++++++++ .../index.html | 12 ++ .../package.json | 40 +++++ .../src/main.jsx | 156 +++++++++++++++++ .../webpack.config.js | 78 +++++++++ .../keyed/reactive-react-redux-v3/index.html | 12 ++ .../package.json | 0 .../src/main.jsx | 0 .../reactive-react-redux-v3/webpack.config.js | 78 +++++++++ 20 files changed, 1145 insertions(+) create mode 100755 frameworks/keyed/react-tracked-useSelector/index.html create mode 100644 frameworks/keyed/react-tracked-useSelector/package.json create mode 100755 frameworks/keyed/react-tracked-useSelector/src/main.jsx rename frameworks/keyed/{reactive-react-redux => react-tracked-useSelector}/webpack.config.js (100%) rename frameworks/keyed/{reactive-react-redux => react-tracked-useTrackedState}/index.html (100%) create mode 100644 frameworks/keyed/react-tracked-useTrackedState/package.json create mode 100755 frameworks/keyed/react-tracked-useTrackedState/src/main.jsx create mode 100755 frameworks/keyed/react-tracked-useTrackedState/webpack.config.js create mode 100755 frameworks/keyed/reactive-react-redux-useSelector/index.html create mode 100644 frameworks/keyed/reactive-react-redux-useSelector/package.json create mode 100755 frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx create mode 100755 frameworks/keyed/reactive-react-redux-useSelector/webpack.config.js create mode 100755 frameworks/keyed/reactive-react-redux-useTrackedState/index.html create mode 100644 frameworks/keyed/reactive-react-redux-useTrackedState/package.json create mode 100755 frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx create mode 100755 frameworks/keyed/reactive-react-redux-useTrackedState/webpack.config.js create mode 100755 frameworks/keyed/reactive-react-redux-v3/index.html rename frameworks/keyed/{reactive-react-redux => reactive-react-redux-v3}/package.json (100%) rename frameworks/keyed/{reactive-react-redux => reactive-react-redux-v3}/src/main.jsx (100%) create mode 100755 frameworks/keyed/reactive-react-redux-v3/webpack.config.js diff --git a/frameworks/keyed/react-tracked-useSelector/index.html b/frameworks/keyed/react-tracked-useSelector/index.html new file mode 100755 index 000000000..bae8383bf --- /dev/null +++ b/frameworks/keyed/react-tracked-useSelector/index.html @@ -0,0 +1,12 @@ + + + + + React + Redux + hooks + + + +
+ + + diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json new file mode 100644 index 000000000..2219bc6bc --- /dev/null +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -0,0 +1,39 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "react-tracked": "0.4.0" + } +} diff --git a/frameworks/keyed/react-tracked-useSelector/src/main.jsx b/frameworks/keyed/react-tracked-useSelector/src/main.jsx new file mode 100755 index 000000000..8d28b846f --- /dev/null +++ b/frameworks/keyed/react-tracked-useSelector/src/main.jsx @@ -0,0 +1,157 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { Provider, useSelector, useDispatch } from 'react-tracked'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const useValue = () => useReducer((state, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}, { data: [], selected: 0 }); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ i }) => { + const selector = useCallback((state) => { + const item = state.data[i]; + return state.selected === item.id ? { id: item.id, label: item.label, selected: true } : item; + }, [i]); + const { selected, id, label } = useSelector(selector); + const dispatch = useDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const data = useSelector(state => state.data); + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

React + Redux + hooks

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/reactive-react-redux/webpack.config.js b/frameworks/keyed/react-tracked-useSelector/webpack.config.js similarity index 100% rename from frameworks/keyed/reactive-react-redux/webpack.config.js rename to frameworks/keyed/react-tracked-useSelector/webpack.config.js diff --git a/frameworks/keyed/reactive-react-redux/index.html b/frameworks/keyed/react-tracked-useTrackedState/index.html similarity index 100% rename from frameworks/keyed/reactive-react-redux/index.html rename to frameworks/keyed/react-tracked-useTrackedState/index.html diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json new file mode 100644 index 000000000..479e74e83 --- /dev/null +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -0,0 +1,39 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:reactive-react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "react-tracked": "0.4.0" + } +} diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx new file mode 100755 index 000000000..3bf0410ba --- /dev/null +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -0,0 +1,156 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createStore } from 'redux'; +import { Provider, useTrackedState, useDispatch } from 'react-tracked'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const useValue = () => useReducer((state, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}, { data: [], selected: 0 }); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ item, selected }) => { + const { id, label } = item; + const dispatch = useDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data, selectedId }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const state = useTrackedState(); + const data = state.data; + const selectedId = state.selected; + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

reactive-react-redux

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/react-tracked-useTrackedState/webpack.config.js b/frameworks/keyed/react-tracked-useTrackedState/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/react-tracked-useTrackedState/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; diff --git a/frameworks/keyed/reactive-react-redux-useSelector/index.html b/frameworks/keyed/reactive-react-redux-useSelector/index.html new file mode 100755 index 000000000..bae8383bf --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useSelector/index.html @@ -0,0 +1,12 @@ + + + + + React + Redux + hooks + + + +
+ + + diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json new file mode 100644 index 000000000..720110235 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -0,0 +1,40 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "reactive-react-redux": "4.0.0-beta.0", + "redux": "4.0.1" + } +} diff --git a/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx new file mode 100755 index 000000000..6ffbf4a55 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx @@ -0,0 +1,158 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createStore } from 'redux'; +import { Provider, useSelector, useDispatch } from 'reactive-react-redux'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const store = createStore((state = { data: [], selected: 0 }, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ i }) => { + const selector = useCallback((state) => { + const item = state.data[i]; + return state.selected === item.id ? { id: item.id, label: item.label, selected: true } : item; + }, [i]); + const { selected, id, label } = useSelector(selector); + const dispatch = useDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const data = useSelector(state => state.data); + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

React + Redux + hooks

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/reactive-react-redux-useSelector/webpack.config.js b/frameworks/keyed/reactive-react-redux-useSelector/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useSelector/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/index.html b/frameworks/keyed/reactive-react-redux-useTrackedState/index.html new file mode 100755 index 000000000..c2ba7599a --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/index.html @@ -0,0 +1,12 @@ + + + + + reactive-react-redux + + + +
+ + + diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json new file mode 100644 index 000000000..33fcd28d6 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json @@ -0,0 +1,40 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react:reactive-react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.2.0", + "@babel/preset-env": "7.2.0", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.2.1", + "babel-loader": "8.0.4", + "terser-webpack-plugin": "1.1.0", + "webpack": "4.27.0", + "webpack-cli": "3.1.2" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "reactive-react-redux": "4.0.0-beta.0", + "redux": "4.0.1" + } +} diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx new file mode 100755 index 000000000..37211be31 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx @@ -0,0 +1,156 @@ +import React, { useCallback } from 'react'; +import ReactDOM from 'react-dom'; +import { createStore } from 'redux'; +import { Provider, useTrackedState, useDispatch } from 'reactive-react-redux'; + +function random(max) { + return Math.round(Math.random() * 1000) % max; +} + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; + +let nextId = 1; + +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const store = createStore((state = { data: [], selected: 0 }, action) => { + const { data, selected } = state; + switch (action.type) { + case 'RUN': + return { data: buildData(1000), selected: 0 }; + case 'RUN_LOTS': + return { data: buildData(10000), selected: 0 }; + case 'ADD': + return { data: data.concat(buildData(1000)), selected }; + case 'UPDATE': + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + case 'REMOVE': + const idx = data.findIndex((d) => d.id === action.id); + return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; + case 'SELECT': + return { data, selected: action.id }; + case 'CLEAR': + return { data: [], selected: 0 }; + case 'SWAP_ROWS': + return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + } + return state; +}); + +function select(id) { + return { type: 'SELECT', id }; +} + +function remove(id) { + return { type: 'REMOVE', id }; +} + +const GlyphIcon = ; + +const Row = React.memo(({ item, selected }) => { + const { id, label } = item; + const dispatch = useDispatch(); + const onSelect = useCallback(() => { + dispatch(select(id)); + }, [dispatch, id]); + const onRemove = useCallback(() => { + dispatch(remove(id)); + }, [dispatch, id]); + return ( + + {id} + {label} + {GlyphIcon} + + + ); +}); + +const InnerRowList = React.memo(({ data, selectedId }) => { + return data.map((item, i) => ); +}); + +const RowList = () => { + const state = useTrackedState(); + const data = state.data; + const selectedId = state.selected; + return ; +}; + +function Button(props) { + return ( +
+ +
+ ); +} + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { + dispatch({ type: 'RUN' }); + }, [dispatch]); + const runLots = useCallback(() => { + dispatch({ type: 'RUN_LOTS' }); + }, [dispatch]); + const add = useCallback(() => { + dispatch({ type: 'ADD' }); + }, [dispatch]); + const update = useCallback(() => { + dispatch({ type: 'UPDATE' }); + }, [dispatch]); + const clear = useCallback(() => { + dispatch({ type: 'CLEAR' }); + }, [dispatch]); + const swapRows = useCallback(() => { + dispatch({ type: 'SWAP_ROWS' }); + }, [dispatch]); + return ( +
+
+
+
+

reactive-react-redux

+
+
+
+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( + ( + +
+ + ), + document.getElementById("main") +); diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/webpack.config.js b/frameworks/keyed/reactive-react-redux-useTrackedState/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; diff --git a/frameworks/keyed/reactive-react-redux-v3/index.html b/frameworks/keyed/reactive-react-redux-v3/index.html new file mode 100755 index 000000000..c2ba7599a --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-v3/index.html @@ -0,0 +1,12 @@ + + + + + reactive-react-redux + + + +
+ + + diff --git a/frameworks/keyed/reactive-react-redux/package.json b/frameworks/keyed/reactive-react-redux-v3/package.json similarity index 100% rename from frameworks/keyed/reactive-react-redux/package.json rename to frameworks/keyed/reactive-react-redux-v3/package.json diff --git a/frameworks/keyed/reactive-react-redux/src/main.jsx b/frameworks/keyed/reactive-react-redux-v3/src/main.jsx similarity index 100% rename from frameworks/keyed/reactive-react-redux/src/main.jsx rename to frameworks/keyed/reactive-react-redux-v3/src/main.jsx diff --git a/frameworks/keyed/reactive-react-redux-v3/webpack.config.js b/frameworks/keyed/reactive-react-redux-v3/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/reactive-react-redux-v3/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; From 77f7649a4df4e05c82980773485d8d81ce459f32 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 16 Jun 2019 22:01:17 +0900 Subject: [PATCH 06/21] fix framework version config --- frameworks/keyed/react-tracked-useSelector/package.json | 2 +- frameworks/keyed/react-tracked-useTrackedState/package.json | 2 +- frameworks/keyed/react-tracked-useTrackedState/src/main.jsx | 1 - frameworks/keyed/reactive-react-redux-useSelector/package.json | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json index 2219bc6bc..a783a0379 100644 --- a/frameworks/keyed/react-tracked-useSelector/package.json +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-redux" + "frameworkVersionFromPackage": "react:react-tracked" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json index 479e74e83..a783a0379 100644 --- a/frameworks/keyed/react-tracked-useTrackedState/package.json +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:reactive-react-redux" + "frameworkVersionFromPackage": "react:react-tracked" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx index 3bf0410ba..36467faae 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -1,6 +1,5 @@ import React, { useCallback } from 'react'; import ReactDOM from 'react-dom'; -import { createStore } from 'redux'; import { Provider, useTrackedState, useDispatch } from 'react-tracked'; function random(max) { diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json index 720110235..33fcd28d6 100644 --- a/frameworks/keyed/reactive-react-redux-useSelector/package.json +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-redux" + "frameworkVersionFromPackage": "react:reactive-react-redux" }, "scripts": { "build-dev": "webpack --watch", From 448d4e74225ea8deb703839934d9992757e9aba2 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 16 Jun 2019 22:11:23 +0900 Subject: [PATCH 07/21] fix imports --- frameworks/keyed/react-tracked-useSelector/src/main.jsx | 2 +- frameworks/keyed/react-tracked-useTrackedState/src/main.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/keyed/react-tracked-useSelector/src/main.jsx b/frameworks/keyed/react-tracked-useSelector/src/main.jsx index 8d28b846f..2192028a0 100755 --- a/frameworks/keyed/react-tracked-useSelector/src/main.jsx +++ b/frameworks/keyed/react-tracked-useSelector/src/main.jsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useReducer } from 'react'; import ReactDOM from 'react-dom'; import { Provider, useSelector, useDispatch } from 'react-tracked'; diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx index 36467faae..c60c35f19 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useReducer } from 'react'; import ReactDOM from 'react-dom'; import { Provider, useTrackedState, useDispatch } from 'react-tracked'; From 1b0538787b91395d8943ece603d8188ba51e7f37 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 16 Jun 2019 22:28:43 +0900 Subject: [PATCH 08/21] change titles, fix useReducer --- frameworks/keyed/react-tracked-useSelector/index.html | 2 +- frameworks/keyed/react-tracked-useSelector/src/main.jsx | 8 +++++--- frameworks/keyed/react-tracked-useTrackedState/index.html | 2 +- .../keyed/react-tracked-useTrackedState/src/main.jsx | 8 +++++--- .../keyed/reactive-react-redux-useSelector/index.html | 2 +- .../keyed/reactive-react-redux-useSelector/src/main.jsx | 2 +- .../reactive-react-redux-useTrackedState/src/main.jsx | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/frameworks/keyed/react-tracked-useSelector/index.html b/frameworks/keyed/react-tracked-useSelector/index.html index bae8383bf..873072985 100755 --- a/frameworks/keyed/react-tracked-useSelector/index.html +++ b/frameworks/keyed/react-tracked-useSelector/index.html @@ -2,7 +2,7 @@ - React + Redux + hooks + react-tracked diff --git a/frameworks/keyed/react-tracked-useSelector/src/main.jsx b/frameworks/keyed/react-tracked-useSelector/src/main.jsx index 2192028a0..d76116938 100755 --- a/frameworks/keyed/react-tracked-useSelector/src/main.jsx +++ b/frameworks/keyed/react-tracked-useSelector/src/main.jsx @@ -23,7 +23,8 @@ function buildData(count) { return data; } -const useValue = () => useReducer((state, action) => { +const initialState = { data: [], selected: 0 }; +const reducer = (state, action) => { const { data, selected } = state; switch (action.type) { case 'RUN': @@ -50,7 +51,8 @@ const useValue = () => useReducer((state, action) => { return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; } return state; -}, { data: [], selected: 0 }); +}; +const useValue = () => useReducer(reducer, initialState); function select(id) { return { type: 'SELECT', id }; @@ -127,7 +129,7 @@ const Main = () => {
-

React + Redux + hooks

+

react-tracked useSelector

diff --git a/frameworks/keyed/react-tracked-useTrackedState/index.html b/frameworks/keyed/react-tracked-useTrackedState/index.html index c2ba7599a..873072985 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/index.html +++ b/frameworks/keyed/react-tracked-useTrackedState/index.html @@ -2,7 +2,7 @@ - reactive-react-redux + react-tracked diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx index c60c35f19..27e827432 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -23,7 +23,8 @@ function buildData(count) { return data; } -const useValue = () => useReducer((state, action) => { +const initialState = { data: [], selected: 0 }; +const reducer = (state, action) => { const { data, selected } = state; switch (action.type) { case 'RUN': @@ -50,7 +51,8 @@ const useValue = () => useReducer((state, action) => { return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; } return state; -}, { data: [], selected: 0 }); +}; +const useValue = () => useReducer(reducer, initialState); function select(id) { return { type: 'SELECT', id }; @@ -125,7 +127,7 @@ const Main = () => {
-

reactive-react-redux

+

react-tracked useTrackedState

diff --git a/frameworks/keyed/reactive-react-redux-useSelector/index.html b/frameworks/keyed/reactive-react-redux-useSelector/index.html index bae8383bf..c2ba7599a 100755 --- a/frameworks/keyed/reactive-react-redux-useSelector/index.html +++ b/frameworks/keyed/reactive-react-redux-useSelector/index.html @@ -2,7 +2,7 @@ - React + Redux + hooks + reactive-react-redux diff --git a/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx index 6ffbf4a55..10a96b9d7 100755 --- a/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx +++ b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx @@ -128,7 +128,7 @@ const Main = () => {
-

React + Redux + hooks

+

reactive-react-redux useSelector

diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx index 37211be31..16eaa0dac 100755 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx @@ -126,7 +126,7 @@ const Main = () => {
-

reactive-react-redux

+

reactive-react-redux useTrackedState

From 55fb0b4e4a283cfc49970900b6685ea10fe5eb64 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 16 Jun 2019 22:47:30 +0900 Subject: [PATCH 09/21] remove react version to show --- frameworks/keyed/react-redux-hooks/package.json | 2 +- frameworks/keyed/react-tracked-useSelector/package.json | 2 +- frameworks/keyed/react-tracked-useTrackedState/package.json | 2 +- frameworks/keyed/reactive-react-redux-useSelector/package.json | 2 +- .../keyed/reactive-react-redux-useTrackedState/package.json | 2 +- frameworks/keyed/reactive-react-redux-v3/package.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frameworks/keyed/react-redux-hooks/package.json b/frameworks/keyed/react-redux-hooks/package.json index a5547a8c1..7db451689 100644 --- a/frameworks/keyed/react-redux-hooks/package.json +++ b/frameworks/keyed/react-redux-hooks/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-redux" + "frameworkVersionFromPackage": "react-redux" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json index a783a0379..596aae63c 100644 --- a/frameworks/keyed/react-tracked-useSelector/package.json +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-tracked" + "frameworkVersionFromPackage": "react-tracked" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json index a783a0379..596aae63c 100644 --- a/frameworks/keyed/react-tracked-useTrackedState/package.json +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-tracked" + "frameworkVersionFromPackage": "react-tracked" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json index 33fcd28d6..fe93ccd15 100644 --- a/frameworks/keyed/reactive-react-redux-useSelector/package.json +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:reactive-react-redux" + "frameworkVersionFromPackage": "reactive-react-redux" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json index 33fcd28d6..fe93ccd15 100644 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:reactive-react-redux" + "frameworkVersionFromPackage": "reactive-react-redux" }, "scripts": { "build-dev": "webpack --watch", diff --git a/frameworks/keyed/reactive-react-redux-v3/package.json b/frameworks/keyed/reactive-react-redux-v3/package.json index b6a591880..08b47268b 100644 --- a/frameworks/keyed/reactive-react-redux-v3/package.json +++ b/frameworks/keyed/reactive-react-redux-v3/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:reactive-react-redux" + "frameworkVersionFromPackage": "reactive-react-redux" }, "scripts": { "build-dev": "webpack --watch", From f7e8f446ed2ecc43ac7587684b74451bb11a0cc9 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 21 Jul 2019 08:32:36 +0900 Subject: [PATCH 10/21] update rrr and react-tracked --- frameworks/keyed/react-tracked-useSelector/package.json | 2 +- frameworks/keyed/react-tracked-useTrackedState/package.json | 2 +- frameworks/keyed/reactive-react-redux-useSelector/package.json | 2 +- .../keyed/reactive-react-redux-useTrackedState/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json index 596aae63c..e1b5e5356 100644 --- a/frameworks/keyed/react-tracked-useSelector/package.json +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -34,6 +34,6 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-tracked": "0.4.0" + "react-tracked": "0.7.0" } } diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json index 596aae63c..e1b5e5356 100644 --- a/frameworks/keyed/react-tracked-useTrackedState/package.json +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -34,6 +34,6 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-tracked": "0.4.0" + "react-tracked": "0.7.0" } } diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json index fe93ccd15..20405aff1 100644 --- a/frameworks/keyed/reactive-react-redux-useSelector/package.json +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.0.0-beta.0", + "reactive-react-redux": "4.1.0", "redux": "4.0.1" } } diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json index fe93ccd15..20405aff1 100644 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.0.0-beta.0", + "reactive-react-redux": "4.1.0", "redux": "4.0.1" } } From d6e3684c30d73862053ada2452f5f58a7bf26427 Mon Sep 17 00:00:00 2001 From: daishi Date: Thu, 8 Aug 2019 19:31:08 +0900 Subject: [PATCH 11/21] renew reactive-react-redux and react-tracked from react-redux-hooks --- .../react-hooks-global-state/package.json | 18 +- .../react-tracked-useSelector/package.json | 14 +- .../react-tracked-useSelector/src/main.jsx | 158 +++++++---------- .../package.json | 14 +- .../src/main.jsx | 155 +++++++---------- .../package.json | 16 +- .../src/main.jsx | 160 +++++++----------- .../package.json | 16 +- .../src/main.jsx | 155 +++++++---------- .../keyed/reactive-react-redux-v3/index.html | 12 -- .../reactive-react-redux-v3/package.json | 40 ----- .../reactive-react-redux-v3/src/main.jsx | 156 ----------------- .../reactive-react-redux-v3/webpack.config.js | 78 --------- 13 files changed, 286 insertions(+), 706 deletions(-) delete mode 100755 frameworks/keyed/reactive-react-redux-v3/index.html delete mode 100644 frameworks/keyed/reactive-react-redux-v3/package.json delete mode 100755 frameworks/keyed/reactive-react-redux-v3/src/main.jsx delete mode 100755 frameworks/keyed/reactive-react-redux-v3/webpack.config.js diff --git a/frameworks/keyed/react-hooks-global-state/package.json b/frameworks/keyed/react-hooks-global-state/package.json index 175ae8042..79f39240e 100644 --- a/frameworks/keyed/react-hooks-global-state/package.json +++ b/frameworks/keyed/react-hooks-global-state/package.json @@ -4,7 +4,7 @@ "description": "React Hooks demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react:react-hooks-global-state" + "frameworkVersionFromPackage": "react-hooks-global-state" }, "scripts": { "build-dev": "webpack --watch", @@ -22,18 +22,18 @@ "url": "https://github.com/krausest/js-framework-benchmark.git" }, "devDependencies": { - "@babel/core": "7.2.2", - "@babel/preset-env": "7.3.1", + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.3.0", - "babel-loader": "8.0.5", - "terser-webpack-plugin": "1.2.2", - "webpack": "4.29.2", - "webpack-cli": "3.2.3" + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" }, "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-hooks-global-state": "0.11.0" + "react-hooks-global-state": "0.14.0" } } diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json index e1b5e5356..210b9b119 100644 --- a/frameworks/keyed/react-tracked-useSelector/package.json +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -22,14 +22,14 @@ "url": "https://github.com/krausest/js-framework-benchmark.git" }, "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.2.1", - "babel-loader": "8.0.4", - "terser-webpack-plugin": "1.1.0", - "webpack": "4.27.0", - "webpack-cli": "3.1.2" + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" }, "dependencies": { "react": "16.8.6", diff --git a/frameworks/keyed/react-tracked-useSelector/src/main.jsx b/frameworks/keyed/react-tracked-useSelector/src/main.jsx index d76116938..4dc867e16 100755 --- a/frameworks/keyed/react-tracked-useSelector/src/main.jsx +++ b/frameworks/keyed/react-tracked-useSelector/src/main.jsx @@ -1,17 +1,17 @@ -import React, { useCallback, useReducer } from 'react'; -import ReactDOM from 'react-dom'; -import { Provider, useSelector, useDispatch } from 'react-tracked'; +import React, { useCallback, useReducer } from "react"; +import ReactDOM from "react-dom"; +import { Provider, useDispatch, useSelector } from "react-tracked"; -function random(max) { - return Math.round(Math.random() * 1000) % max; -} - -const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; -const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; -let nextId = 1; +const random = (max) => Math.round(Math.random() * 1000) % max; +let nextId = 1; function buildData(count) { const data = new Array(count); for (let i = 0; i < count; i++) { @@ -27,120 +27,90 @@ const initialState = { data: [], selected: 0 }; const reducer = (state, action) => { const { data, selected } = state; switch (action.type) { - case 'RUN': + case "RUN": return { data: buildData(1000), selected: 0 }; - case 'RUN_LOTS': + case "RUN_LOTS": return { data: buildData(10000), selected: 0 }; - case 'ADD': + case "ADD": return { data: data.concat(buildData(1000)), selected }; - case 'UPDATE': + case "UPDATE": { const newData = data.slice(); for (let i = 0; i < newData.length; i += 10) { const r = newData[i]; newData[i] = { id: r.id, label: r.label + " !!!" }; } return { data: newData, selected }; - case 'REMOVE': - const idx = data.findIndex((d) => d.id === action.id); - return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; - case 'SELECT': + } + case "REMOVE": { + const newData = data.slice(); + newData.splice(data.indexOf(action.item), 1); + return { data: newData, selected }; + } + case "SELECT": return { data, selected: action.id }; - case 'CLEAR': + case "CLEAR": return { data: [], selected: 0 }; - case 'SWAP_ROWS': - return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } } return state; }; const useValue = () => useReducer(reducer, initialState); -function select(id) { - return { type: 'SELECT', id }; -} - -function remove(id) { - return { type: 'REMOVE', id }; -} - const GlyphIcon = ; -const Row = React.memo(({ i }) => { - const selector = useCallback((state) => { - const item = state.data[i]; - return state.selected === item.id ? { id: item.id, label: item.label, selected: true } : item; - }, [i]); - const { selected, id, label } = useSelector(selector); +const Row = React.memo(({ data }) => { + const isSelected = useSelector((state) => state.selected === data.id); const dispatch = useDispatch(); - const onSelect = useCallback(() => { - dispatch(select(id)); - }, [dispatch, id]); - const onRemove = useCallback(() => { - dispatch(remove(id)); - }, [dispatch, id]); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); return ( - - {id} - {label} - {GlyphIcon} + + {data.id} + {data.label} + {GlyphIcon} - ); + ) }); -const InnerRowList = React.memo(({ data }) => { - return data.map((item, i) => ); +const RowList = React.memo(() => { + const rows = useSelector((state) => state.data); + return rows.map((data) => ); }); -const RowList = () => { - const data = useSelector(state => state.data); - return ; -}; - -function Button(props) { - return ( -
- -
- ); -} +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); const Main = () => { const dispatch = useDispatch(); - const run = useCallback(() => { - dispatch({ type: 'RUN' }); - }, [dispatch]); - const runLots = useCallback(() => { - dispatch({ type: 'RUN_LOTS' }); - }, [dispatch]); - const add = useCallback(() => { - dispatch({ type: 'ADD' }); - }, [dispatch]); - const update = useCallback(() => { - dispatch({ type: 'UPDATE' }); - }, [dispatch]); - const clear = useCallback(() => { - dispatch({ type: 'CLEAR' }); - }, [dispatch]); - const swapRows = useCallback(() => { - dispatch({ type: 'SWAP_ROWS' }); - }, [dispatch]); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); return (
-
-

react-tracked useSelector

-
-
-
-
-
+

react-tracked useSelector

+
+
@@ -150,10 +120,6 @@ const Main = () => { }; ReactDOM.render( - ( - -
- - ), +
, document.getElementById("main") ); diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json index e1b5e5356..210b9b119 100644 --- a/frameworks/keyed/react-tracked-useTrackedState/package.json +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -22,14 +22,14 @@ "url": "https://github.com/krausest/js-framework-benchmark.git" }, "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.2.1", - "babel-loader": "8.0.4", - "terser-webpack-plugin": "1.1.0", - "webpack": "4.27.0", - "webpack-cli": "3.1.2" + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" }, "dependencies": { "react": "16.8.6", diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx index 27e827432..57a5542e0 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -1,17 +1,17 @@ -import React, { useCallback, useReducer } from 'react'; -import ReactDOM from 'react-dom'; -import { Provider, useTrackedState, useDispatch } from 'react-tracked'; +import React, { useCallback, useReducer } from "react"; +import ReactDOM from "react-dom"; +import { Provider, useDispatch, useTrackedState } from "react-tracked"; -function random(max) { - return Math.round(Math.random() * 1000) % max; -} - -const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; -const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; -let nextId = 1; +const random = (max) => Math.round(Math.random() * 1000) % max; +let nextId = 1; function buildData(count) { const data = new Array(count); for (let i = 0; i < count; i++) { @@ -24,121 +24,92 @@ function buildData(count) { } const initialState = { data: [], selected: 0 }; -const reducer = (state, action) => { +const reducer = (state , action) => { const { data, selected } = state; switch (action.type) { - case 'RUN': + case "RUN": return { data: buildData(1000), selected: 0 }; - case 'RUN_LOTS': + case "RUN_LOTS": return { data: buildData(10000), selected: 0 }; - case 'ADD': + case "ADD": return { data: data.concat(buildData(1000)), selected }; - case 'UPDATE': + case "UPDATE": { const newData = data.slice(); for (let i = 0; i < newData.length; i += 10) { const r = newData[i]; newData[i] = { id: r.id, label: r.label + " !!!" }; } return { data: newData, selected }; - case 'REMOVE': - const idx = data.findIndex((d) => d.id === action.id); - return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; - case 'SELECT': + } + case "REMOVE": { + const newData = data.slice(); + newData.splice(data.indexOf(action.item), 1); + return { data: newData, selected }; + } + case "SELECT": return { data, selected: action.id }; - case 'CLEAR': + case "CLEAR": return { data: [], selected: 0 }; - case 'SWAP_ROWS': - return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } } return state; }; const useValue = () => useReducer(reducer, initialState); -function select(id) { - return { type: 'SELECT', id }; -} - -function remove(id) { - return { type: 'REMOVE', id }; -} - const GlyphIcon = ; -const Row = React.memo(({ item, selected }) => { - const { id, label } = item; +const Row = React.memo(({ data, selected }) => { const dispatch = useDispatch(); - const onSelect = useCallback(() => { - dispatch(select(id)); - }, [dispatch, id]); - const onRemove = useCallback(() => { - dispatch(remove(id)); - }, [dispatch, id]); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); return ( - {id} - {label} - {GlyphIcon} + {data.id} + {data.label} + {GlyphIcon} - ); -}); - -const InnerRowList = React.memo(({ data, selectedId }) => { - return data.map((item, i) => ); + ) }); -const RowList = () => { +const RowList = React.memo(() => { const state = useTrackedState(); - const data = state.data; - const selectedId = state.selected; - return ; -}; + return state.data.map((data) => ); +}); -function Button(props) { - return ( -
- -
- ); -} +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); const Main = () => { const dispatch = useDispatch(); - const run = useCallback(() => { - dispatch({ type: 'RUN' }); - }, [dispatch]); - const runLots = useCallback(() => { - dispatch({ type: 'RUN_LOTS' }); - }, [dispatch]); - const add = useCallback(() => { - dispatch({ type: 'ADD' }); - }, [dispatch]); - const update = useCallback(() => { - dispatch({ type: 'UPDATE' }); - }, [dispatch]); - const clear = useCallback(() => { - dispatch({ type: 'CLEAR' }); - }, [dispatch]); - const swapRows = useCallback(() => { - dispatch({ type: 'SWAP_ROWS' }); - }, [dispatch]); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); return (
-
-

react-tracked useTrackedState

-
-
-
-
-
+

react-tracked useTrackedState

+
+
@@ -148,10 +119,6 @@ const Main = () => { }; ReactDOM.render( - ( - -
- - ), +
, document.getElementById("main") ); diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json index 20405aff1..fc3d53b6c 100644 --- a/frameworks/keyed/reactive-react-redux-useSelector/package.json +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -22,19 +22,19 @@ "url": "https://github.com/krausest/js-framework-benchmark.git" }, "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.2.1", - "babel-loader": "8.0.4", - "terser-webpack-plugin": "1.1.0", - "webpack": "4.27.0", - "webpack-cli": "3.1.2" + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" }, "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.1.0", + "reactive-react-redux": "4.2.0", "redux": "4.0.1" } } diff --git a/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx index 10a96b9d7..0a96807db 100755 --- a/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx +++ b/frameworks/keyed/reactive-react-redux-useSelector/src/main.jsx @@ -1,18 +1,18 @@ -import React, { useCallback } from 'react'; -import ReactDOM from 'react-dom'; -import { createStore } from 'redux'; -import { Provider, useSelector, useDispatch } from 'reactive-react-redux'; +import React, { useCallback } from "react"; +import ReactDOM from "react-dom"; +import { createStore } from "redux"; +import { Provider, useDispatch, useSelector } from "reactive-react-redux"; -function random(max) { - return Math.round(Math.random() * 1000) % max; -} - -const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; -const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; -let nextId = 1; +const random = (max) => Math.round(Math.random() * 1000) % max; +let nextId = 1; function buildData(count) { const data = new Array(count); for (let i = 0; i < count; i++) { @@ -27,119 +27,89 @@ function buildData(count) { const store = createStore((state = { data: [], selected: 0 }, action) => { const { data, selected } = state; switch (action.type) { - case 'RUN': + case "RUN": return { data: buildData(1000), selected: 0 }; - case 'RUN_LOTS': + case "RUN_LOTS": return { data: buildData(10000), selected: 0 }; - case 'ADD': + case "ADD": return { data: data.concat(buildData(1000)), selected }; - case 'UPDATE': + case "UPDATE": { const newData = data.slice(); for (let i = 0; i < newData.length; i += 10) { const r = newData[i]; newData[i] = { id: r.id, label: r.label + " !!!" }; } return { data: newData, selected }; - case 'REMOVE': - const idx = data.findIndex((d) => d.id === action.id); - return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; - case 'SELECT': + } + case "REMOVE": { + const newData = data.slice(); + newData.splice(data.indexOf(action.item), 1); + return { data: newData, selected }; + } + case "SELECT": return { data, selected: action.id }; - case 'CLEAR': + case "CLEAR": return { data: [], selected: 0 }; - case 'SWAP_ROWS': - return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } } return state; }); -function select(id) { - return { type: 'SELECT', id }; -} - -function remove(id) { - return { type: 'REMOVE', id }; -} - const GlyphIcon = ; -const Row = React.memo(({ i }) => { - const selector = useCallback((state) => { - const item = state.data[i]; - return state.selected === item.id ? { id: item.id, label: item.label, selected: true } : item; - }, [i]); - const { selected, id, label } = useSelector(selector); +const Row = React.memo(({ data }) => { + const isSelected = useSelector((state) => state.selected === data.id); const dispatch = useDispatch(); - const onSelect = useCallback(() => { - dispatch(select(id)); - }, [dispatch, id]); - const onRemove = useCallback(() => { - dispatch(remove(id)); - }, [dispatch, id]); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); return ( - - {id} - {label} - {GlyphIcon} + + {data.id} + {data.label} + {GlyphIcon} - ); + ) }); -const InnerRowList = React.memo(({ data }) => { - return data.map((item, i) => ); +const RowList = React.memo(() => { + const rows = useSelector((state) => state.data); + return rows.map((data) => ); }); -const RowList = () => { - const data = useSelector(state => state.data); - return ; -}; - -function Button(props) { - return ( -
- -
- ); -} +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); const Main = () => { const dispatch = useDispatch(); - const run = useCallback(() => { - dispatch({ type: 'RUN' }); - }, [dispatch]); - const runLots = useCallback(() => { - dispatch({ type: 'RUN_LOTS' }); - }, [dispatch]); - const add = useCallback(() => { - dispatch({ type: 'ADD' }); - }, [dispatch]); - const update = useCallback(() => { - dispatch({ type: 'UPDATE' }); - }, [dispatch]); - const clear = useCallback(() => { - dispatch({ type: 'CLEAR' }); - }, [dispatch]); - const swapRows = useCallback(() => { - dispatch({ type: 'SWAP_ROWS' }); - }, [dispatch]); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); return (
-
-

reactive-react-redux useSelector

-
-
-
-
-
+

reactive-react-redux useSelector

+
+
@@ -149,10 +119,6 @@ const Main = () => { }; ReactDOM.render( - ( - -
- - ), +
, document.getElementById("main") ); diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json index 20405aff1..fc3d53b6c 100644 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json @@ -22,19 +22,19 @@ "url": "https://github.com/krausest/js-framework-benchmark.git" }, "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.2.1", - "babel-loader": "8.0.4", - "terser-webpack-plugin": "1.1.0", - "webpack": "4.27.0", - "webpack-cli": "3.1.2" + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" }, "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.1.0", + "reactive-react-redux": "4.2.0", "redux": "4.0.1" } } diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx index 16eaa0dac..24df6f7bf 100755 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx @@ -1,18 +1,18 @@ -import React, { useCallback } from 'react'; -import ReactDOM from 'react-dom'; -import { createStore } from 'redux'; -import { Provider, useTrackedState, useDispatch } from 'reactive-react-redux'; +import React, { useCallback } from "react"; +import ReactDOM from "react-dom"; +import { createStore } from "redux"; +import { Provider, useDispatch, useTrackedState } from "reactive-react-redux"; -function random(max) { - return Math.round(Math.random() * 1000) % max; -} - -const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; -const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; -let nextId = 1; +const random = (max) => Math.round(Math.random() * 1000) % max; +let nextId = 1; function buildData(count) { const data = new Array(count); for (let i = 0; i < count; i++) { @@ -27,117 +27,88 @@ function buildData(count) { const store = createStore((state = { data: [], selected: 0 }, action) => { const { data, selected } = state; switch (action.type) { - case 'RUN': + case "RUN": return { data: buildData(1000), selected: 0 }; - case 'RUN_LOTS': + case "RUN_LOTS": return { data: buildData(10000), selected: 0 }; - case 'ADD': + case "ADD": return { data: data.concat(buildData(1000)), selected }; - case 'UPDATE': + case "UPDATE": { const newData = data.slice(); for (let i = 0; i < newData.length; i += 10) { const r = newData[i]; newData[i] = { id: r.id, label: r.label + " !!!" }; } return { data: newData, selected }; - case 'REMOVE': - const idx = data.findIndex((d) => d.id === action.id); - return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; - case 'SELECT': + } + case "REMOVE": { + const newData = data.slice(); + newData.splice(data.indexOf(action.item), 1); + return { data: newData, selected }; + } + case "SELECT": return { data, selected: action.id }; - case 'CLEAR': + case "CLEAR": return { data: [], selected: 0 }; - case 'SWAP_ROWS': - return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } } return state; }); -function select(id) { - return { type: 'SELECT', id }; -} - -function remove(id) { - return { type: 'REMOVE', id }; -} - const GlyphIcon = ; -const Row = React.memo(({ item, selected }) => { - const { id, label } = item; +const Row = React.memo(({ data, selected }) => { const dispatch = useDispatch(); - const onSelect = useCallback(() => { - dispatch(select(id)); - }, [dispatch, id]); - const onRemove = useCallback(() => { - dispatch(remove(id)); - }, [dispatch, id]); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); return ( - {id} - {label} - {GlyphIcon} + {data.id} + {data.label} + {GlyphIcon} - ); -}); - -const InnerRowList = React.memo(({ data, selectedId }) => { - return data.map((item, i) => ); + ) }); -const RowList = () => { +const RowList = React.memo(() => { const state = useTrackedState(); - const data = state.data; - const selectedId = state.selected; - return ; -}; + return state.data.map((data) => ); +}); -function Button(props) { - return ( -
- -
- ); -} +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); const Main = () => { const dispatch = useDispatch(); - const run = useCallback(() => { - dispatch({ type: 'RUN' }); - }, [dispatch]); - const runLots = useCallback(() => { - dispatch({ type: 'RUN_LOTS' }); - }, [dispatch]); - const add = useCallback(() => { - dispatch({ type: 'ADD' }); - }, [dispatch]); - const update = useCallback(() => { - dispatch({ type: 'UPDATE' }); - }, [dispatch]); - const clear = useCallback(() => { - dispatch({ type: 'CLEAR' }); - }, [dispatch]); - const swapRows = useCallback(() => { - dispatch({ type: 'SWAP_ROWS' }); - }, [dispatch]); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); return (
-
-

reactive-react-redux useTrackedState

-
-
-
-
-
+

reactive-react-redux useTrackedState

+
+
@@ -147,10 +118,6 @@ const Main = () => { }; ReactDOM.render( - ( - -
- - ), +
, document.getElementById("main") ); diff --git a/frameworks/keyed/reactive-react-redux-v3/index.html b/frameworks/keyed/reactive-react-redux-v3/index.html deleted file mode 100755 index c2ba7599a..000000000 --- a/frameworks/keyed/reactive-react-redux-v3/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - reactive-react-redux - - - -
- - - diff --git a/frameworks/keyed/reactive-react-redux-v3/package.json b/frameworks/keyed/reactive-react-redux-v3/package.json deleted file mode 100644 index 08b47268b..000000000 --- a/frameworks/keyed/reactive-react-redux-v3/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "js-framework-benchmark-react", - "version": "1.1.1", - "description": "React demo", - "main": "index.js", - "js-framework-benchmark": { - "frameworkVersionFromPackage": "reactive-react-redux" - }, - "scripts": { - "build-dev": "webpack --watch", - "build-prod": "webpack" - }, - "keywords": [ - "react", - "webpack" - ], - "author": "Stefan Krause", - "license": "Apache-2.0", - "homepage": "https://github.com/krausest/js-framework-benchmark", - "repository": { - "type": "git", - "url": "https://github.com/krausest/js-framework-benchmark.git" - }, - "devDependencies": { - "@babel/core": "7.2.0", - "@babel/preset-env": "7.2.0", - "@babel/preset-react": "7.0.0", - "@babel/plugin-proposal-class-properties": "7.2.1", - "babel-loader": "8.0.4", - "terser-webpack-plugin": "1.1.0", - "webpack": "4.27.0", - "webpack-cli": "3.1.2" - }, - "dependencies": { - "react": "16.8.6", - "react-dom": "16.8.6", - "reactive-react-redux": "3.0.0", - "redux": "4.0.1" - } -} diff --git a/frameworks/keyed/reactive-react-redux-v3/src/main.jsx b/frameworks/keyed/reactive-react-redux-v3/src/main.jsx deleted file mode 100755 index 9dd440656..000000000 --- a/frameworks/keyed/reactive-react-redux-v3/src/main.jsx +++ /dev/null @@ -1,156 +0,0 @@ -import React, { useCallback } from 'react'; -import ReactDOM from 'react-dom'; -import { createStore } from 'redux'; -import { ReduxProvider, useReduxState, useReduxDispatch } from 'reactive-react-redux'; - -function random(max) { - return Math.round(Math.random() * 1000) % max; -} - -const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", "cheap", "expensive", "fancy"]; -const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; -const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", "keyboard"]; - -let nextId = 1; - -function buildData(count) { - const data = new Array(count); - for (let i = 0; i < count; i++) { - data[i] = { - id: nextId++, - label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, - } - } - return data; -} - -const store = createStore((state = { data: [], selected: 0 }, action) => { - const { data, selected } = state; - switch (action.type) { - case 'RUN': - return { data: buildData(1000), selected: 0 }; - case 'RUN_LOTS': - return { data: buildData(10000), selected: 0 }; - case 'ADD': - return { data: data.concat(buildData(1000)), selected }; - case 'UPDATE': - const newData = data.slice(); - for (let i = 0; i < newData.length; i += 10) { - const r = newData[i]; - newData[i] = { id: r.id, label: r.label + " !!!" }; - } - return { data: newData, selected }; - case 'REMOVE': - const idx = data.findIndex((d) => d.id === action.id); - return { data: [...data.slice(0, idx), ...data.slice(idx + 1)], selected }; - case 'SELECT': - return { data, selected: action.id }; - case 'CLEAR': - return { data: [], selected: 0 }; - case 'SWAP_ROWS': - return { data: [data[0], data[998], ...data.slice(2, 998), data[1], data[999]], selected }; - } - return state; -}); - -function select(id) { - return { type: 'SELECT', id }; -} - -function remove(id) { - return { type: 'REMOVE', id }; -} - -const GlyphIcon = ; - -const Row = React.memo(({ item, selected }) => { - const { id, label } = item; - const dispatch = useReduxDispatch(); - const onSelect = useCallback(() => { - dispatch(select(id)); - }, [dispatch, id]); - const onRemove = useCallback(() => { - dispatch(remove(id)); - }, [dispatch, id]); - return ( - - {id} - {label} - {GlyphIcon} - - - ); -}); - -const InnerRowList = React.memo(({ data, selectedId }) => { - return data.map((item, i) => ); -}); - -const RowList = () => { - const state = useReduxState(); - const data = state.data; - const selectedId = state.selected; - return ; -}; - -function Button(props) { - return ( -
- -
- ); -} - -const Main = () => { - const dispatch = useReduxDispatch(); - const run = useCallback(() => { - dispatch({ type: 'RUN' }); - }, [dispatch]); - const runLots = useCallback(() => { - dispatch({ type: 'RUN_LOTS' }); - }, [dispatch]); - const add = useCallback(() => { - dispatch({ type: 'ADD' }); - }, [dispatch]); - const update = useCallback(() => { - dispatch({ type: 'UPDATE' }); - }, [dispatch]); - const clear = useCallback(() => { - dispatch({ type: 'CLEAR' }); - }, [dispatch]); - const swapRows = useCallback(() => { - dispatch({ type: 'SWAP_ROWS' }); - }, [dispatch]); - return ( -
-
-
-
-

reactive-react-redux

-
-
-
-
-
-
-
-
- -
- ); -}; - -ReactDOM.render( - ( - -
- - ), - document.getElementById("main") -); diff --git a/frameworks/keyed/reactive-react-redux-v3/webpack.config.js b/frameworks/keyed/reactive-react-redux-v3/webpack.config.js deleted file mode 100755 index f6607fcc0..000000000 --- a/frameworks/keyed/reactive-react-redux-v3/webpack.config.js +++ /dev/null @@ -1,78 +0,0 @@ -const path = require('path'); -const webpack = require('webpack'); -const TerserPlugin = require('terser-webpack-plugin'); - -module.exports = { - mode: 'production', - // mode: 'development', - entry: { - main: path.join(__dirname, 'src', 'main.jsx'), - }, - output: { - path: path.join(__dirname, 'dist'), - filename: '[name].js' - }, - resolve: { - extensions: ['.js', '.jsx'] - }, - module: { - rules: [{ - test: /\.jsx?$/, - exclude: /node_modules/, - use: [ - { - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env', '@babel/preset-react'], - plugins: ['@babel/plugin-proposal-class-properties'], - } - } - ] - }] - }, - optimization: { - minimizer: [ - new TerserPlugin({ - terserOptions: { - parse: { - // we want terser to parse ecma 8 code. However, we don't want it - // to apply any minfication steps that turns valid ecma 5 code - // into invalid ecma 5 code. This is why the 'compress' and 'output' - // sections only apply transformations that are ecma 5 safe - // https://github.com/facebook/create-react-app/pull/4234 - ecma: 8, - }, - compress: { - ecma: 5, - warnings: false, - // Disabled because of an issue with Uglify breaking seemingly valid code: - // https://github.com/facebook/create-react-app/issues/2376 - // Pending further investigation: - // https://github.com/mishoo/UglifyJS2/issues/2011 - comparisons: false, - }, - mangle: { - safari10: true, - }, - output: { - ecma: 5, - comments: false, - // Turned on because emoji and regex is not minified properly using default - // https://github.com/facebook/create-react-app/issues/2488 - ascii_only: true, - }, - }, - // Use multi-process parallel running to improve the build speed - // Default number of concurrent runs: os.cpus().length - 1 - parallel: true, - // Enable file caching - cache: true, - }), - ] - }, - plugins: [ - new webpack.DefinePlugin({ - 'process.env': { NODE_ENV: JSON.stringify('production') } - }), - ], -}; From 1574a86c64a2c6b88dedda2bb9eed3d696055527 Mon Sep 17 00:00:00 2001 From: daishi Date: Thu, 8 Aug 2019 21:27:21 +0900 Subject: [PATCH 12/21] fix for useTrackedState --- frameworks/keyed/react-tracked-useTrackedState/src/main.jsx | 5 +++-- .../keyed/reactive-react-redux-useTrackedState/src/main.jsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx index 57a5542e0..20e88fd92 100755 --- a/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx +++ b/frameworks/keyed/react-tracked-useTrackedState/src/main.jsx @@ -42,8 +42,9 @@ const reducer = (state , action) => { return { data: newData, selected }; } case "REMOVE": { + const idx = data.findIndex(d => d.id === action.id); const newData = data.slice(); - newData.splice(data.indexOf(action.item), 1); + newData.splice(idx, 1); return { data: newData, selected }; } case "SELECT": @@ -67,7 +68,7 @@ const GlyphIcon = { dispatch({ type: "REMOVE", item: data }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", id: data.id }); }, [data]); return ( {data.id} diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx index 24df6f7bf..6fc70ab25 100755 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/src/main.jsx @@ -42,8 +42,9 @@ const store = createStore((state = { data: [], selected: 0 }, action) => { return { data: newData, selected }; } case "REMOVE": { + const idx = data.findIndex(d => d.id === action.id); const newData = data.slice(); - newData.splice(data.indexOf(action.item), 1); + newData.splice(idx, 1); return { data: newData, selected }; } case "SELECT": @@ -66,7 +67,7 @@ const GlyphIcon = { dispatch({ type: "REMOVE", item: data }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", id: data.id }); }, [data]); return ( {data.id} From 5756315fd5db20f5118e74cb745f935b6c07b8ef Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 18 Aug 2019 02:31:59 +0900 Subject: [PATCH 13/21] react-redux-hooks-worker --- .../keyed/react-redux-hooks-worker/index.html | 12 +++ .../react-redux-hooks-worker/package.json | 42 ++++++++++ .../react-redux-hooks-worker/src/main.jsx | 71 ++++++++++++++++ .../src/store.worker.js | 64 +++++++++++++++ .../webpack.config.js | 81 +++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100755 frameworks/keyed/react-redux-hooks-worker/index.html create mode 100644 frameworks/keyed/react-redux-hooks-worker/package.json create mode 100755 frameworks/keyed/react-redux-hooks-worker/src/main.jsx create mode 100755 frameworks/keyed/react-redux-hooks-worker/src/store.worker.js create mode 100755 frameworks/keyed/react-redux-hooks-worker/webpack.config.js diff --git a/frameworks/keyed/react-redux-hooks-worker/index.html b/frameworks/keyed/react-redux-hooks-worker/index.html new file mode 100755 index 000000000..17e95220c --- /dev/null +++ b/frameworks/keyed/react-redux-hooks-worker/index.html @@ -0,0 +1,12 @@ + + + + + React + Redux + + + +
+ + + diff --git a/frameworks/keyed/react-redux-hooks-worker/package.json b/frameworks/keyed/react-redux-hooks-worker/package.json new file mode 100644 index 000000000..bb978c9c0 --- /dev/null +++ b/frameworks/keyed/react-redux-hooks-worker/package.json @@ -0,0 +1,42 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "react-redux" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.4.5", + "@babel/plugin-proposal-class-properties": "7.4.4", + "@babel/preset-env": "7.4.5", + "@babel/preset-react": "7.0.0", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4", + "worker-plugin": "^3.1.0" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "react-redux": "7.1.0", + "redux": "4.0.1", + "redux-in-worker": "0.2.0" + } +} diff --git a/frameworks/keyed/react-redux-hooks-worker/src/main.jsx b/frameworks/keyed/react-redux-hooks-worker/src/main.jsx new file mode 100755 index 000000000..3197fe8a4 --- /dev/null +++ b/frameworks/keyed/react-redux-hooks-worker/src/main.jsx @@ -0,0 +1,71 @@ +import React, { useCallback } from "react"; +import ReactDOM from "react-dom"; +import { wrapStore } from "redux-in-worker"; +import { Provider, useDispatch, useSelector } from "react-redux"; + +import { initialState } from "./store.worker"; + +const worker = new Worker("./store.worker", { type: "module" }); +const store = wrapStore(worker, initialState); + +const GlyphIcon = ; + +const Row = React.memo(({ data }) => { + const isSelected = useSelector((state) => state.selected === data.id); + const dispatch = useDispatch(); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", id: data.id }); }, [data]); + return ( + + {data.id} + {data.label} + {GlyphIcon} + + + ) +}); + +const RowList = React.memo(() => { + const rows = useSelector((state) => state.data); + return rows.map((data) => ); +}); + +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); + return ( +
+
+
+

React + Redux

+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( +
, + document.getElementById("main") +); diff --git a/frameworks/keyed/react-redux-hooks-worker/src/store.worker.js b/frameworks/keyed/react-redux-hooks-worker/src/store.worker.js new file mode 100755 index 000000000..9a0b2a2e4 --- /dev/null +++ b/frameworks/keyed/react-redux-hooks-worker/src/store.worker.js @@ -0,0 +1,64 @@ +import { createStore } from "redux"; +import { exposeStore } from "redux-in-worker"; + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; + +const random = (max) => Math.round(Math.random() * 1000) % max; + +let nextId = 1; +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +export const initialState = { data: [], selected: 0 }; +const store = createStore((state = initialState, action) => { + const { data, selected } = state; + switch (action.type) { + case "RUN": + return { data: buildData(1000), selected: 0 }; + case "RUN_LOTS": + return { data: buildData(10000), selected: 0 }; + case "ADD": + return { data: data.concat(buildData(1000)), selected }; + case "UPDATE": { + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + } + case "REMOVE": { + const idx = data.findIndex(d => d.id === action.id); + const newData = data.slice(); + newData.splice(idx, 1); + return { data: newData, selected }; + } + case "SELECT": + return { data, selected: action.id }; + case "CLEAR": + return { data: [], selected: 0 }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } + } + return state; +}); + +exposeStore(store); diff --git a/frameworks/keyed/react-redux-hooks-worker/webpack.config.js b/frameworks/keyed/react-redux-hooks-worker/webpack.config.js new file mode 100755 index 000000000..ee7ffddfc --- /dev/null +++ b/frameworks/keyed/react-redux-hooks-worker/webpack.config.js @@ -0,0 +1,81 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); +const WorkerPlugin = require('worker-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js', + publicPath: 'dist/' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + new WorkerPlugin(), + ], +}; From 99a46df89593df794a255b9e28cb85e31827dd57 Mon Sep 17 00:00:00 2001 From: daishi Date: Sun, 18 Aug 2019 12:30:38 +0900 Subject: [PATCH 14/21] redux-in-worker v0.3.0 --- frameworks/keyed/react-redux-hooks-worker/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/keyed/react-redux-hooks-worker/package.json b/frameworks/keyed/react-redux-hooks-worker/package.json index bb978c9c0..ab756a2bb 100644 --- a/frameworks/keyed/react-redux-hooks-worker/package.json +++ b/frameworks/keyed/react-redux-hooks-worker/package.json @@ -4,7 +4,7 @@ "description": "React demo", "main": "index.js", "js-framework-benchmark": { - "frameworkVersionFromPackage": "react-redux" + "frameworkVersionFromPackage": "react-redux:redux-in-worker" }, "scripts": { "build-dev": "webpack --watch", @@ -37,6 +37,6 @@ "react-dom": "16.8.6", "react-redux": "7.1.0", "redux": "4.0.1", - "redux-in-worker": "0.2.0" + "redux-in-worker": "0.3.0" } } From 3336bd261c1f219e0c875237f1384d6d3e4bc1f6 Mon Sep 17 00:00:00 2001 From: daishi Date: Tue, 20 Aug 2019 11:27:31 +0900 Subject: [PATCH 15/21] redux-in-worker v0.6.0 --- frameworks/keyed/react-redux-hooks-worker/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/keyed/react-redux-hooks-worker/package.json b/frameworks/keyed/react-redux-hooks-worker/package.json index ab756a2bb..6797bf5dd 100644 --- a/frameworks/keyed/react-redux-hooks-worker/package.json +++ b/frameworks/keyed/react-redux-hooks-worker/package.json @@ -37,6 +37,6 @@ "react-dom": "16.8.6", "react-redux": "7.1.0", "redux": "4.0.1", - "redux-in-worker": "0.3.0" + "redux-in-worker": "0.6.0" } } From 7bf75244aa24418c53f621770ccb25c856c76bb3 Mon Sep 17 00:00:00 2001 From: daishi Date: Thu, 22 Aug 2019 10:35:32 +0900 Subject: [PATCH 16/21] update deps --- frameworks/keyed/react-redux-hooks-worker/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/keyed/react-redux-hooks-worker/package.json b/frameworks/keyed/react-redux-hooks-worker/package.json index 6797bf5dd..8daa094a5 100644 --- a/frameworks/keyed/react-redux-hooks-worker/package.json +++ b/frameworks/keyed/react-redux-hooks-worker/package.json @@ -37,6 +37,6 @@ "react-dom": "16.8.6", "react-redux": "7.1.0", "redux": "4.0.1", - "redux-in-worker": "0.6.0" + "redux-in-worker": "0.7.0" } } From fb012608bfa29a15767be9dd7a404f4945dcae0e Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 21 Feb 2020 11:37:35 +0900 Subject: [PATCH 17/21] update packages --- frameworks/keyed/react-hooks-global-state/package.json | 2 +- frameworks/keyed/react-tracked-useSelector/package.json | 2 +- frameworks/keyed/react-tracked-useTrackedState/package.json | 2 +- frameworks/keyed/reactive-react-redux-useSelector/package.json | 2 +- .../keyed/reactive-react-redux-useTrackedState/package.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/keyed/react-hooks-global-state/package.json b/frameworks/keyed/react-hooks-global-state/package.json index 79f39240e..8593af612 100644 --- a/frameworks/keyed/react-hooks-global-state/package.json +++ b/frameworks/keyed/react-hooks-global-state/package.json @@ -34,6 +34,6 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-hooks-global-state": "0.14.0" + "react-hooks-global-state": "1.0.0" } } diff --git a/frameworks/keyed/react-tracked-useSelector/package.json b/frameworks/keyed/react-tracked-useSelector/package.json index 210b9b119..6f6716532 100644 --- a/frameworks/keyed/react-tracked-useSelector/package.json +++ b/frameworks/keyed/react-tracked-useSelector/package.json @@ -34,6 +34,6 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-tracked": "0.7.0" + "react-tracked": "1.0.6" } } diff --git a/frameworks/keyed/react-tracked-useTrackedState/package.json b/frameworks/keyed/react-tracked-useTrackedState/package.json index 210b9b119..6f6716532 100644 --- a/frameworks/keyed/react-tracked-useTrackedState/package.json +++ b/frameworks/keyed/react-tracked-useTrackedState/package.json @@ -34,6 +34,6 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "react-tracked": "0.7.0" + "react-tracked": "1.0.6" } } diff --git a/frameworks/keyed/reactive-react-redux-useSelector/package.json b/frameworks/keyed/reactive-react-redux-useSelector/package.json index fc3d53b6c..1352de4ac 100644 --- a/frameworks/keyed/reactive-react-redux-useSelector/package.json +++ b/frameworks/keyed/reactive-react-redux-useSelector/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.2.0", + "reactive-react-redux": "4.5.0", "redux": "4.0.1" } } diff --git a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json index fc3d53b6c..1352de4ac 100644 --- a/frameworks/keyed/reactive-react-redux-useTrackedState/package.json +++ b/frameworks/keyed/reactive-react-redux-useTrackedState/package.json @@ -34,7 +34,7 @@ "dependencies": { "react": "16.8.6", "react-dom": "16.8.6", - "reactive-react-redux": "4.2.0", + "reactive-react-redux": "4.5.0", "redux": "4.0.1" } } From af09c088a340e74c705ce3883f9c9dbf83db3512 Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 21 Feb 2020 12:05:46 +0900 Subject: [PATCH 18/21] update react-hooks-global-state --- frameworks/keyed/react-hooks-global-state/src/main.jsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frameworks/keyed/react-hooks-global-state/src/main.jsx b/frameworks/keyed/react-hooks-global-state/src/main.jsx index a0a629f4c..d202e24e0 100644 --- a/frameworks/keyed/react-hooks-global-state/src/main.jsx +++ b/frameworks/keyed/react-hooks-global-state/src/main.jsx @@ -24,7 +24,7 @@ function buildData(count) { return data; } -const { GlobalStateProvider, useGlobalState, setGlobalState } = createGlobalState({ data: [], selected: 0 }); +const { useGlobalState, setGlobalState } = createGlobalState({ data: [], selected: 0 }); function doAction(action) { switch (action.type) { @@ -125,9 +125,7 @@ const Main = () => { ReactDOM.render( ( - -
- +
), document.getElementById('main') ); From 1078750db7be499a8d46e9ee30f0cbdc52edf0eb Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 21 Feb 2020 12:34:13 +0900 Subject: [PATCH 19/21] new redux + use-context-selector --- .../index.html | 12 ++ .../package.json | 40 +++++ .../src/main.jsx | 142 ++++++++++++++++++ .../webpack.config.js | 78 ++++++++++ 4 files changed, 272 insertions(+) create mode 100755 frameworks/keyed/react-redux-use-context-selector/index.html create mode 100644 frameworks/keyed/react-redux-use-context-selector/package.json create mode 100755 frameworks/keyed/react-redux-use-context-selector/src/main.jsx create mode 100755 frameworks/keyed/react-redux-use-context-selector/webpack.config.js diff --git a/frameworks/keyed/react-redux-use-context-selector/index.html b/frameworks/keyed/react-redux-use-context-selector/index.html new file mode 100755 index 000000000..5245ca3f6 --- /dev/null +++ b/frameworks/keyed/react-redux-use-context-selector/index.html @@ -0,0 +1,12 @@ + + + + + Redux + useContextSelector + + + +
+ + + diff --git a/frameworks/keyed/react-redux-use-context-selector/package.json b/frameworks/keyed/react-redux-use-context-selector/package.json new file mode 100644 index 000000000..c0f547cd3 --- /dev/null +++ b/frameworks/keyed/react-redux-use-context-selector/package.json @@ -0,0 +1,40 @@ +{ + "name": "js-framework-benchmark-react", + "version": "1.1.1", + "description": "React demo", + "main": "index.js", + "js-framework-benchmark": { + "frameworkVersionFromPackage": "use-context-selector" + }, + "scripts": { + "build-dev": "webpack --watch", + "build-prod": "webpack" + }, + "keywords": [ + "react", + "webpack" + ], + "author": "Stefan Krause", + "license": "Apache-2.0", + "homepage": "https://github.com/krausest/js-framework-benchmark", + "repository": { + "type": "git", + "url": "https://github.com/krausest/js-framework-benchmark.git" + }, + "devDependencies": { + "@babel/core": "7.4.5", + "@babel/preset-env": "7.4.5", + "@babel/preset-react": "7.0.0", + "@babel/plugin-proposal-class-properties": "7.4.4", + "babel-loader": "8.0.6", + "terser-webpack-plugin": "1.3.0", + "webpack": "4.34.0", + "webpack-cli": "3.3.4" + }, + "dependencies": { + "react": "16.8.6", + "react-dom": "16.8.6", + "redux": "4.0.1", + "use-context-selector": "1.0.1" + } +} diff --git a/frameworks/keyed/react-redux-use-context-selector/src/main.jsx b/frameworks/keyed/react-redux-use-context-selector/src/main.jsx new file mode 100755 index 000000000..9d1ca18ce --- /dev/null +++ b/frameworks/keyed/react-redux-use-context-selector/src/main.jsx @@ -0,0 +1,142 @@ +import React, { useCallback, useState, useEffect } from "react"; +import ReactDOM from "react-dom"; +import { createStore } from "redux"; +import { createContext, useContextSelector } from "use-context-selector"; + +const DispatchContext = createContext(); +const StateContext = createContext(); +const Provider = ({ store, children }) => { + const [state, setState] = useState(store.getState()); + useEffect(() => { + return store.subscribe(() => setState(store.getState())); + }, []); + return ( + + + {children} + + + ); +}; +const useDispatch = () => useContextSelector(DispatchContext, x => x); +const useSelector = (selector) => useContextSelector(StateContext, selector); + +const A = ["pretty", "large", "big", "small", "tall", "short", "long", "handsome", "plain", "quaint", "clean", + "elegant", "easy", "angry", "crazy", "helpful", "mushy", "odd", "unsightly", "adorable", "important", "inexpensive", + "cheap", "expensive", "fancy"]; +const C = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"]; +const N = ["table", "chair", "house", "bbq", "desk", "car", "pony", "cookie", "sandwich", "burger", "pizza", "mouse", + "keyboard"]; + +const random = (max) => Math.round(Math.random() * 1000) % max; + +let nextId = 1; +function buildData(count) { + const data = new Array(count); + for (let i = 0; i < count; i++) { + data[i] = { + id: nextId++, + label: `${A[random(A.length)]} ${C[random(C.length)]} ${N[random(N.length)]}`, + } + } + return data; +} + +const store = createStore((state = { data: [], selected: 0 }, action) => { + const { data, selected } = state; + switch (action.type) { + case "RUN": + return { data: buildData(1000), selected: 0 }; + case "RUN_LOTS": + return { data: buildData(10000), selected: 0 }; + case "ADD": + return { data: data.concat(buildData(1000)), selected }; + case "UPDATE": { + const newData = data.slice(); + for (let i = 0; i < newData.length; i += 10) { + const r = newData[i]; + newData[i] = { id: r.id, label: r.label + " !!!" }; + } + return { data: newData, selected }; + } + case "REMOVE": { + const newData = data.slice(); + newData.splice(data.indexOf(action.item), 1); + return { data: newData, selected }; + } + case "SELECT": + return { data, selected: action.id }; + case "CLEAR": + return { data: [], selected: 0 }; + case "SWAP_ROWS": { + const newData = data.slice(); + const tmp = newData[1]; + newData[1] = newData[998]; + newData[998] = tmp; + return { data: newData, selected }; + } + } + return state; +}); + +const GlyphIcon = ; + +const Row = React.memo(({ data }) => { + const isSelected = useSelector((state) => state.selected === data.id); + const dispatch = useDispatch(); + const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); + return ( + + {data.id} + {data.label} + {GlyphIcon} + + + ) +}); + +const RowList = React.memo(() => { + const rows = useSelector((state) => state.data); + return rows.map((data) => ); +}); + +const Button = React.memo(({ id, title, cb }) => ( +
+ +
+)); + +const Main = () => { + const dispatch = useDispatch(); + const run = useCallback(() => { dispatch({ type: "RUN" }); }, []); + const runLots = useCallback(() => { dispatch({ type: "RUN_LOTS" }); }, []); + const add = useCallback(() => { dispatch({ type: "ADD" }); }, []); + const update = useCallback(() => { dispatch({ type: "UPDATE" }); }, []); + const clear = useCallback(() => { dispatch({ type: "CLEAR" }); }, []); + const swapRows = useCallback(() => { dispatch({ type: "SWAP_ROWS" }); }, []); + return ( +
+
+
+

React + Redux

+
+
+
+
+
+ +
+ ); +}; + +ReactDOM.render( +
, + document.getElementById("main") +); diff --git a/frameworks/keyed/react-redux-use-context-selector/webpack.config.js b/frameworks/keyed/react-redux-use-context-selector/webpack.config.js new file mode 100755 index 000000000..f6607fcc0 --- /dev/null +++ b/frameworks/keyed/react-redux-use-context-selector/webpack.config.js @@ -0,0 +1,78 @@ +const path = require('path'); +const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); + +module.exports = { + mode: 'production', + // mode: 'development', + entry: { + main: path.join(__dirname, 'src', 'main.jsx'), + }, + output: { + path: path.join(__dirname, 'dist'), + filename: '[name].js' + }, + resolve: { + extensions: ['.js', '.jsx'] + }, + module: { + rules: [{ + test: /\.jsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env', '@babel/preset-react'], + plugins: ['@babel/plugin-proposal-class-properties'], + } + } + ] + }] + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + // we want terser to parse ecma 8 code. However, we don't want it + // to apply any minfication steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + }, + mangle: { + safari10: true, + }, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + // Use multi-process parallel running to improve the build speed + // Default number of concurrent runs: os.cpus().length - 1 + parallel: true, + // Enable file caching + cache: true, + }), + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { NODE_ENV: JSON.stringify('production') } + }), + ], +}; From 0e1dc0483182320b60111b42c8df11bfb684ee89 Mon Sep 17 00:00:00 2001 From: daishi Date: Fri, 21 Feb 2020 16:28:53 +0900 Subject: [PATCH 20/21] use callback properly --- .../react-redux-use-context-selector/src/main.jsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/frameworks/keyed/react-redux-use-context-selector/src/main.jsx b/frameworks/keyed/react-redux-use-context-selector/src/main.jsx index 9d1ca18ce..4ab234432 100755 --- a/frameworks/keyed/react-redux-use-context-selector/src/main.jsx +++ b/frameworks/keyed/react-redux-use-context-selector/src/main.jsx @@ -82,13 +82,14 @@ const store = createStore((state = { data: [], selected: 0 }, action) => { const GlyphIcon = ; const Row = React.memo(({ data }) => { - const isSelected = useSelector((state) => state.selected === data.id); + const dataId = data.id; + const isSelected = useSelector(useCallback((state) => state.selected === dataId, [dataId])); const dispatch = useDispatch(); - const select = useCallback(() => { dispatch({ type: "SELECT", id: data.id }); }, [data]); + const select = useCallback(() => { dispatch({ type: "SELECT", id: dataId }); }, [dataId]); const remove = useCallback(() => { dispatch({ type: "REMOVE", item: data }); }, [data]); return ( - {data.id} + {dataId} {data.label} {GlyphIcon} @@ -97,7 +98,7 @@ const Row = React.memo(({ data }) => { }); const RowList = React.memo(() => { - const rows = useSelector((state) => state.data); + const rows = useSelector(useCallback((state) => state.data, [])); return rows.map((data) => ); }); @@ -119,7 +120,7 @@ const Main = () => {
-

React + Redux

+

Redux + useContextSelector