diff --git a/.gitignore b/.gitignore index 6206c35..d35cf00 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ coverage *.patch .DS_STORE +.idea/ +yarn.lock diff --git a/examples/immutable-persist-counter/.babelrc b/examples/immutable-persist-counter/.babelrc new file mode 100644 index 0000000..b5c69c4 --- /dev/null +++ b/examples/immutable-persist-counter/.babelrc @@ -0,0 +1,15 @@ +{ + "presets": [ + "es2015", + "stage-2", + "react" + ], + "plugins": [ + ["transform-runtime", { + "helpers": false, + "polyfill": false, + "regenerator": true + }] + ] +} + diff --git a/examples/immutable-persist-counter/README.md b/examples/immutable-persist-counter/README.md new file mode 100644 index 0000000..313d84e --- /dev/null +++ b/examples/immutable-persist-counter/README.md @@ -0,0 +1,8 @@ +## Counter + +### Get started + +```js +npm i +npm start +``` diff --git a/examples/immutable-persist-counter/package.json b/examples/immutable-persist-counter/package.json new file mode 100644 index 0000000..f61a946 --- /dev/null +++ b/examples/immutable-persist-counter/package.json @@ -0,0 +1,32 @@ +{ + "name": "mirror-counter-example", + "version": "0.1.0", + "description": "Mirror counter example", + "scripts": { + "start": "webpack-dev-server --open", + "build": "cross-env NODE_ENV=production webpack -p" + }, + "dependencies": { + "babel-runtime": "^6.23.0", + "mirrorx": "^0.2.12", + "prop-types": "^15.5.10", + "react": "^15.0.0", + "react-dom": "^15.0.0", + "redux-persist": "^5.10.0", + "redux-persist-transform-immutable": "^5.0.0" + }, + "devDependencies": { + "babel-cli": "^6.14.1", + "babel-core": "^6.14.1", + "babel-loader": "^7.0.0", + "babel-plugin-transform-runtime": "^6.23.0", + "babel-preset-es2015": "^6.14.1", + "babel-preset-react": "^6.14.1", + "babel-preset-stage-2": "^6.14.1", + "cross-env": "^5.0.1", + "css-loader": "^0.28.4", + "style-loader": "^0.18.2", + "webpack": "^2.6.0", + "webpack-dev-server": "^2.4.5" + } +} diff --git a/examples/immutable-persist-counter/public/index.html b/examples/immutable-persist-counter/public/index.html new file mode 100644 index 0000000..21e3130 --- /dev/null +++ b/examples/immutable-persist-counter/public/index.html @@ -0,0 +1,12 @@ + + + + + Mirror - Counter Example + + +
+ + + + diff --git a/examples/immutable-persist-counter/src/App.css b/examples/immutable-persist-counter/src/App.css new file mode 100644 index 0000000..7fdb1d9 --- /dev/null +++ b/examples/immutable-persist-counter/src/App.css @@ -0,0 +1,41 @@ +body { + height: 100vh; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + margin: 0; +} + +#root { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +} + +#counter-app { + width: 300px; +} + +h1 { + font-size: 180px; + margin: 0; + text-align: center; +} + +.btn-wrap { + display: flex; + align-items: center; + justify-content: space-around; +} + +button { + background-color: #fff; + border: 1px solid #999; + border-radius: 2px; + font-size: 120%; + outline: none; + width: 60px; + cursor: pointer; +} diff --git a/examples/immutable-persist-counter/src/App.js b/examples/immutable-persist-counter/src/App.js new file mode 100644 index 0000000..f3cef19 --- /dev/null +++ b/examples/immutable-persist-counter/src/App.js @@ -0,0 +1,44 @@ +import React from 'react' +import mirror, {actions, connect} from 'mirrorx' + +import './App.css' + +mirror.model({ + name: 'app', + initialState: 0, + reducers: { + increment(state) { + return state + 1 + }, + decrement(state) { + return state - 1 + } + }, + effects: { + async incrementAsync() { + await new Promise((resolve, reject) => { + setTimeout(() => { + resolve() + }, 1000) + }) + actions.app.increment() + } + } +}) + +const App = props => { + return ( +
+

{props.count}

+
+ + + +
+
+ ) +} + +export default connect(state => { + return {count: state.app} +})(App) diff --git a/examples/immutable-persist-counter/src/index.js b/examples/immutable-persist-counter/src/index.js new file mode 100644 index 0000000..b2bd665 --- /dev/null +++ b/examples/immutable-persist-counter/src/index.js @@ -0,0 +1,10 @@ +import React from 'react' + +import mirror, { render, Router, Route } from 'mirrorx' +import App from './App' +import { persist } from './persist' + +const callback = (createStore, reducer, initialState, enhancer) => ( + persist(createStore, reducer, initialState, enhancer)) + +render(, document.getElementById('root'), null, callback) diff --git a/examples/immutable-persist-counter/src/persist.js b/examples/immutable-persist-counter/src/persist.js new file mode 100644 index 0000000..78084eb --- /dev/null +++ b/examples/immutable-persist-counter/src/persist.js @@ -0,0 +1,23 @@ +import { persistStore, persistReducer } from 'redux-persist' +import immutableTransform from 'redux-persist-transform-immutable' +import storage from 'redux-persist/lib/storage' + +const config = { + key: 'root', + storage, + transforms: [immutableTransform()], +} + +export let store, persistor + +export function persist(createStore, rootReducer, initializeState, enhancer) { + let reducer = persistReducer(config, rootReducer) + store = createStore(reducer, initializeState, enhancer) + persistor = persistStore(store) + return store +} + +export default { + persistor, + store, +} diff --git a/examples/immutable-persist-counter/webpack.config.js b/examples/immutable-persist-counter/webpack.config.js new file mode 100644 index 0000000..3279048 --- /dev/null +++ b/examples/immutable-persist-counter/webpack.config.js @@ -0,0 +1,72 @@ +const path = require('path') +const webpack = require('webpack') + +const config = { + // in development, + // 'webpack-dev-server/client' and 'webpac/hot/dev-server' will be automatically added + entry: [ + './src/index.js' + ], + output: { + path: path.resolve(__dirname, 'build'), + filename: 'app.js', + publicPath: '/' + }, + module: { + rules: [ + { + test: /\.jsx?$/, + include: [ + path.resolve(__dirname, 'src') + ], + loader: 'babel-loader' + }, + { + test: /\.css$/, + use: [ + { + loader: 'style-loader', + }, + { + loader: 'css-loader', + } + ] + } + ] + } +} + +if (process.env.NODE_ENV === 'production') { + + config.devtool = 'source-map' + + // Exclude react and react-dom in the production bundle + config.externals = { + 'react': 'React', + 'react-dom': 'ReactDOM' + } + +} else { + + config.devtool = 'cheap-module-source-map' + + config.devServer = { + contentBase: path.resolve(__dirname, 'public'), + clientLogLevel: 'none', + quiet: true, + port: 8000, + compress: true, + hot: true, + historyApiFallback: { + disableDotRule: true + } + } + + // HMR support + config.plugins = [ + new webpack.HotModuleReplacementPlugin(), + new webpack.NamedModulesPlugin() + ] +} + +module.exports = config diff --git a/src/render.js b/src/render.js index 1403493..d53f691 100644 --- a/src/render.js +++ b/src/render.js @@ -9,7 +9,10 @@ import { store, createStore, replaceReducer } from './store' let started = false let Root -export default function render(component, container, callback) { +const defaultCallback = + (createStore, rootReducer, initialState, enhancer) => createStore(rootReducer, initialState, enhancer) + +export default function render(component, container, callback, cb) { const { initialState, middlewares, reducers } = options @@ -25,14 +28,15 @@ export default function render(component, container, callback) { } } else { - createStore(models, reducers, initialState, middlewares) + let _callback = (typeof cb === 'undefined') ? defaultCallback : cb + createStore(_callback, models, reducers, initialState, middlewares) } // Use named function get a proper displayName Root = function Root() { return ( - {component} + {(typeof component) === 'function' ? component() : component} ) } diff --git a/src/store.js b/src/store.js index 576b389..aff2695 100644 --- a/src/store.js +++ b/src/store.js @@ -11,7 +11,7 @@ import routerMiddleware from './routerMiddleware' export let store -export function createStore(models, reducers, initialState, middlewares = []) { +export function createStore(callback, models, reducers, initialState, middlewares = []) { const middleware = applyMiddleware( routerMiddleware(), @@ -35,7 +35,7 @@ export function createStore(models, reducers, initialState, middlewares = []) { const reducer = createReducer(models, reducers) const enhancer = composeEnhancers(...enhancers) - store = _createStore(reducer, initialState, enhancer) + store = callback(_createStore, reducer, initialState, enhancer) return store }