diff --git a/README.md b/README.md
index 8de1e2e..edb9598 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ ActionCreator + ActionSelector, reducers are created automatically
[coverage-report](https://edtoken.github.io/redux-tide/coverage/lcov-report/index.html)
-[![Join the chat at https://gitter.im/practice-feature/redux-tide](https://badges.gitter.im/practice-feature/redux-tide.svg)](https://gitter.im/practice-feature/redux-tide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Join the chat at https://gitter.im/practice-feature/redux-tide](https://badges.gitter.im/practice-feature/redux-tide.svg)](https://gitter.im/practice-feature/redux-tide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![npm version](https://badge.fury.io/js/redux-tide.svg)](https://badge.fury.io/js/redux-tide)
[![Build Status](https://api.travis-ci.org/edtoken/redux-tide.svg?branch=master)](https://travis-ci.org/edtoken/redux-tide)
@@ -96,7 +96,7 @@ npm install redux-thunk --save
------
### Discussion
You can connect to [Gitter chat room](https://gitter.im/practice-feature/redux-tide)
-[![Join the chat at https://gitter.im/practice-feature/redux-tide](https://badges.gitter.im/practice-feature/redux-tide.svg)](https://gitter.im/practice-feature/redux-tide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Join the chat at https://gitter.im/practice-feature/redux-tide](https://badges.gitter.im/practice-feature/redux-tide.svg)](https://gitter.im/practice-feature/redux-tide?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### Usage
1. You might install library
diff --git a/lib/action.js b/lib/action.js
index 726f6b9..7ff5de8 100644
--- a/lib/action.js
+++ b/lib/action.js
@@ -389,28 +389,31 @@ var makeAction = function makeAction(actionId, parentActionId, actionSchema, act
};
};
- // /**
- // * Clean entity from entity reducer
- // *
- // * @memberOf action.makeAction.Action
- // * @type {Function}
- // *
- // * @example
- // * store.dispatch(userLoginAction.clean())
- // *
- // * @returns {Undefined} - returns None, only clear entity data
- // */
- // this.action.clean = () => {
- // return (dispatch, getState) => {
- // dispatch({
- // time: new Date().getTime(),
- // type: ACTION_CLEAN_TYPE_NAME,
- // prefix: ACTION_TYPE_PREFIX,
- // actionId: this.actionId,
- // actionSchema: this.schema
- // })
- // }
- // }
+ /**
+ * Delete entity from entity reducer
+ *
+ * @memberOf action.makeAction.Action
+ * @type {Function}
+ *
+ * @example
+ * store.dispatch(userDeleteAction.delete())
+ *
+ * @example
+ * store.dispatch(userDeleteAction.withPrefix(userId).delete())
+ *
+ * @returns {Undefined} - returns None, only delete entity data
+ */
+ this.action.delete = function () {
+ return function (dispatch, getState) {
+ dispatch({
+ time: new Date().getTime(),
+ type: _config.ACTION_DELETE_TYPE_NAME,
+ prefix: _config.ACTION_TYPE_PREFIX,
+ actionId: _this.actionId,
+ actionSchema: _this.schema
+ });
+ };
+ };
return this.action;
};
diff --git a/lib/config.js b/lib/config.js
index c15190a..de498ed 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -83,7 +83,7 @@ var ACTION_EMPTY_TYPE_NAME = exports.ACTION_EMPTY_TYPE_NAME = ACTION_TYPE_PREFIX
* @const
* @type {String}
*/
-var ACTION_CLEAN_TYPE_NAME = exports.ACTION_CLEAN_TYPE_NAME = ACTION_TYPE_PREFIX + '-clean';
+var ACTION_DELETE_TYPE_NAME = exports.ACTION_DELETE_TYPE_NAME = ACTION_TYPE_PREFIX + '-clean';
/**
* replaced default response mapper to callback
diff --git a/lib/reducer.js b/lib/reducer.js
index 7f13aac..04c33da 100644
--- a/lib/reducer.js
+++ b/lib/reducer.js
@@ -67,6 +67,12 @@ var makeActionsReducer = function makeActionsReducer(defaultActionsState) {
actionState = state.get(actionId);
}
+ // delete entity id from actions
+ if (action.type === _config.ACTION_DELETE_TYPE_NAME) {
+ console.log('action delete', actionState);
+ return state;
+ }
+
actionState = actionState.merge({
status: status,
time: time,
@@ -121,6 +127,12 @@ var makeEntitiesReducer = function makeEntitiesReducer(defaultEntitiesState) {
var newEntitiesItems = normalizedPayloadSource ? normalizedPayloadSource.entities : {};
+ // delete entity id from actions
+ if (action.type === _config.ACTION_DELETE_TYPE_NAME) {
+ console.log('reducer delete');
+ return state;
+ }
+
// merge entity item data
for (var entityName in newEntitiesItems) {
for (var entityId in newEntitiesItems[entityName]) {
diff --git a/src/action.js b/src/action.js
index 2fd9a61..54540fd 100644
--- a/src/action.js
+++ b/src/action.js
@@ -3,8 +3,8 @@
*/
import {
+ ACTION_DELETE_TYPE_NAME,
ACTION_EMPTY_TYPE_NAME,
- ACTION_CLEAN_TYPE_NAME,
ACTION_ID_KEY,
ACTION_IDS_KEY,
ACTION_TYPE_PREFIX,
@@ -447,28 +447,31 @@ const makeAction = function(
}
}
- // /**
- // * Clean entity from entity reducer
- // *
- // * @memberOf action.makeAction.Action
- // * @type {Function}
- // *
- // * @example
- // * store.dispatch(userLoginAction.clean())
- // *
- // * @returns {Undefined} - returns None, only clear entity data
- // */
- // this.action.clean = () => {
- // return (dispatch, getState) => {
- // dispatch({
- // time: new Date().getTime(),
- // type: ACTION_CLEAN_TYPE_NAME,
- // prefix: ACTION_TYPE_PREFIX,
- // actionId: this.actionId,
- // actionSchema: this.schema
- // })
- // }
- // }
+ /**
+ * Delete entity from entity reducer
+ *
+ * @memberOf action.makeAction.Action
+ * @type {Function}
+ *
+ * @example
+ * store.dispatch(userDeleteAction.delete())
+ *
+ * @example
+ * store.dispatch(userDeleteAction.withPrefix(userId).delete())
+ *
+ * @returns {Undefined} - returns None, only delete entity data
+ */
+ this.action.delete = () => {
+ return (dispatch, getState) => {
+ dispatch({
+ time: new Date().getTime(),
+ type: ACTION_DELETE_TYPE_NAME,
+ prefix: ACTION_TYPE_PREFIX,
+ actionId: this.actionId,
+ actionSchema: this.schema
+ })
+ }
+ }
return this.action
}
diff --git a/src/config.js b/src/config.js
index a92a4b0..942f9c5 100644
--- a/src/config.js
+++ b/src/config.js
@@ -78,7 +78,7 @@ export const ACTION_EMPTY_TYPE_NAME = `${ACTION_TYPE_PREFIX}-empty`
* @const
* @type {String}
*/
-export const ACTION_CLEAN_TYPE_NAME = `${ACTION_TYPE_PREFIX}-clean`
+export const ACTION_DELETE_TYPE_NAME = `${ACTION_TYPE_PREFIX}-clean`
/**
* replaced default response mapper to callback
diff --git a/src/index.js b/src/index.js
index 12fc961..41f13e9 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,11 +3,11 @@ import { createReducers } from './reducer'
import {
denomalizeEntityItemById,
getActionData,
- getMergedActionsData,
getEntityItemsByAction,
getEntityItemsByEntityName,
getEntityItemsBySchema,
- getEntityReducer
+ getEntityReducer,
+ getMergedActionsData
} from './selector'
import {
diff --git a/src/reducer.js b/src/reducer.js
index 2780fb0..ed21c27 100644
--- a/src/reducer.js
+++ b/src/reducer.js
@@ -6,6 +6,7 @@ import { fromJS } from 'immutable'
import { normalize } from 'normalizr'
import {
+ ACTION_DELETE_TYPE_NAME,
ACTION_EMPTY_TYPE_NAME,
ACTION_TYPE_PREFIX,
ACTIONS_REDUCER_NAME,
@@ -67,6 +68,12 @@ const makeActionsReducer = defaultActionsState => {
actionState = state.get(actionId)
}
+ // delete entity id from actions
+ if (action.type === ACTION_DELETE_TYPE_NAME) {
+ console.log('action delete', actionState)
+ return state
+ }
+
actionState = actionState.merge({
status,
time,
@@ -136,6 +143,12 @@ const makeEntitiesReducer = defaultEntitiesState => {
? normalizedPayloadSource.entities
: {}
+ // delete entity id from actions
+ if (action.type === ACTION_DELETE_TYPE_NAME) {
+ console.log('reducer delete')
+ return state
+ }
+
// merge entity item data
for (let entityName in newEntitiesItems) {
for (let entityId in newEntitiesItems[entityName]) {
diff --git a/test/action.spec.js b/test/action.spec.js
index 7f75bad..678da6b 100644
--- a/test/action.spec.js
+++ b/test/action.spec.js
@@ -1,16 +1,14 @@
import 'should'
import sinon from 'sinon'
import { schema } from 'normalizr'
-
-require('should-sinon')
-
import {
+ createAction,
makeActionHandler,
- makeActionUniqId,
- makeAction,
- createAction
+ makeActionUniqId
} from '../src/action'
+require('should-sinon')
+
describe('action makeActionUniqId ', function() {
it('makeActionUniqId returns uniquie ids', function() {
const result = new Set([
diff --git a/test/config.spec.js b/test/config.spec.js
index 6104f83..28f2406 100644
--- a/test/config.spec.js
+++ b/test/config.spec.js
@@ -1,24 +1,23 @@
import 'should'
import sinon from 'sinon'
import { schema } from 'normalizr'
-
-require('should-sinon')
-
import {
- IS_TEST_ENVIRONMENT,
- STATUSES,
+ ACTION_EMPTY_TYPE_NAME,
ACTION_ID_KEY,
ACTION_IDS_KEY,
ACTION_TYPE_PREFIX,
ACTIONS_REDUCER_NAME,
ENTITIES_REDUCER_NAME,
- ACTION_EMPTY_TYPE_NAME,
+ IS_TEST_ENVIRONMENT,
setDefaultResponseMapper,
- setDenormalize
+ setDenormalize,
+ STATUSES
} from '../src/config'
import { createAction } from '../src/action'
+require('should-sinon')
+
describe('config is valid', function() {
it('should define all required variables', function() {
IS_TEST_ENVIRONMENT.should.not.be.undefined()
diff --git a/test/helper.spec.js b/test/helper.spec.js
index ed1bdcd..7d11602 100644
--- a/test/helper.spec.js
+++ b/test/helper.spec.js
@@ -1,4 +1,4 @@
-import { uniqPrefix, parseError } from '../src/helper'
+import { parseError, uniqPrefix } from '../src/helper'
describe('helper uniqPrefix', function() {
it('created uniq prefixed', function() {
diff --git a/test/selector.spec.js b/test/selector.spec.js
index cf27dec..a6e8b0f 100644
--- a/test/selector.spec.js
+++ b/test/selector.spec.js
@@ -2,7 +2,7 @@ import 'should'
import { schema } from 'normalizr'
import { fromJS } from 'immutable'
-import { ENTITIES_REDUCER_NAME, ACTIONS_REDUCER_NAME } from '../src/config'
+import { ACTIONS_REDUCER_NAME, ENTITIES_REDUCER_NAME } from '../src/config'
import {
getActionData,
getEntityItemsByAction,
diff --git a/website/package.json b/website/package.json
index 6f17121..978e5f6 100644
--- a/website/package.json
+++ b/website/package.json
@@ -3,32 +3,13 @@
"version": "0.1.0",
"private": true,
"dependencies": {
- "autoprefixer": "7.1.6",
- "babel-core": "6.26.0",
- "babel-eslint": "7.2.3",
- "babel-jest": "20.0.3",
- "babel-loader": "7.1.2",
- "babel-preset-react-app": "^3.1.0",
- "babel-runtime": "6.26.0",
+ "axios": "^0.17.1",
+ "redux-tide": "^0.1.4",
"case-sensitive-paths-webpack-plugin": "2.1.1",
"chalk": "1.1.3",
- "css-loader": "0.28.7",
"dotenv": "4.0.0",
- "eslint": "4.10.0",
- "eslint-config-react-app": "^2.0.1",
- "eslint-loader": "1.9.0",
- "eslint-plugin-flowtype": "2.39.1",
- "eslint-plugin-import": "2.8.0",
- "eslint-plugin-jsx-a11y": "5.1.1",
- "eslint-plugin-react": "7.4.0",
- "extract-text-webpack-plugin": "3.0.2",
- "file-loader": "1.1.5",
"fs-extra": "3.0.1",
"history": "^4.7.2",
- "html-loader": "^0.5.4",
- "html-webpack-plugin": "2.29.0",
- "jest": "20.0.4",
- "markdown-loader": "^2.0.2",
"normalizr": "^3.2.4",
"object-assign": "4.1.1",
"postcss-flexbugs-fixes": "3.2.0",
@@ -46,12 +27,6 @@
"redux-devtools-dock-monitor": "^1.1.3",
"redux-devtools-log-monitor": "^1.4.0",
"redux-thunk": "^2.2.0",
- "style-loader": "0.19.0",
- "sw-precache-webpack-plugin": "0.11.4",
- "url-loader": "0.6.2",
- "webpack": "3.8.1",
- "webpack-dev-server": "2.9.4",
- "webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"
},
"scripts": {
@@ -59,7 +34,36 @@
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom"
},
- "devDependencies": {},
+ "devDependencies": {
+ "codesandbox": "^1.1.14",
+ "autoprefixer": "7.1.6",
+ "babel-core": "6.26.0",
+ "babel-eslint": "7.2.3",
+ "babel-jest": "20.0.3",
+ "babel-loader": "7.1.2",
+ "babel-preset-react-app": "^3.1.0",
+ "babel-runtime": "6.26.0",
+ "eslint": "4.10.0",
+ "eslint-config-react-app": "^2.0.1",
+ "eslint-loader": "1.9.0",
+ "eslint-plugin-flowtype": "2.39.1",
+ "eslint-plugin-import": "2.8.0",
+ "eslint-plugin-jsx-a11y": "5.1.1",
+ "eslint-plugin-react": "7.4.0",
+ "style-loader": "0.19.0",
+ "sw-precache-webpack-plugin": "0.11.4",
+ "url-loader": "0.6.2",
+ "webpack": "3.8.1",
+ "webpack-dev-server": "2.9.4",
+ "webpack-manifest-plugin": "1.3.2",
+ "css-loader": "0.28.7",
+ "extract-text-webpack-plugin": "3.0.2",
+ "file-loader": "1.1.5",
+ "html-loader": "^0.5.4",
+ "html-webpack-plugin": "2.29.0",
+ "markdown-loader": "^2.0.2",
+ "jest": "20.0.4"
+ },
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx,mjs}"
diff --git a/website/src/App.css b/website/src/App.css
index 8456cbf..9eaeb28 100644
--- a/website/src/App.css
+++ b/website/src/App.css
@@ -1,30 +1,34 @@
.App {
- text-align: center;
+ text-align: center;
}
.App-logo {
- animation: App-logo-spin infinite 20s linear;
- height: 80px;
+ animation: App-logo-spin infinite 20s linear;
+ height: 80px;
}
.App-header {
- background-color: #222;
- height: 150px;
- padding: 20px;
- color: white;
+ background-color: #222;
+ height: 150px;
+ padding: 20px;
+ color: white;
}
.App-title {
- font-size: 1.5em;
+ font-size: 1.5em;
}
.App-intro {
- font-size: large;
+ font-size: large;
}
@keyframes App-logo-spin {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
}
.spinner {
@@ -55,18 +59,23 @@
}
@-webkit-keyframes sk-bouncedelay {
- 0%, 80%, 100% { -webkit-transform: scale(0) }
- 40% { -webkit-transform: scale(1.0) }
+ 0%, 80%, 100% {
+ -webkit-transform: scale(0)
+ }
+ 40% {
+ -webkit-transform: scale(1.0)
+ }
}
@keyframes sk-bouncedelay {
0%, 80%, 100% {
-webkit-transform: scale(0);
transform: scale(0);
- } 40% {
- -webkit-transform: scale(1.0);
- transform: scale(1.0);
- }
+ }
+ 40% {
+ -webkit-transform: scale(1.0);
+ transform: scale(1.0);
+ }
}
.spinner {
@@ -97,16 +106,21 @@
}
@-webkit-keyframes sk-bouncedelay {
- 0%, 80%, 100% { -webkit-transform: scale(0) }
- 40% { -webkit-transform: scale(1.0) }
+ 0%, 80%, 100% {
+ -webkit-transform: scale(0)
+ }
+ 40% {
+ -webkit-transform: scale(1.0)
+ }
}
@keyframes sk-bouncedelay {
0%, 80%, 100% {
-webkit-transform: scale(0);
transform: scale(0);
- } 40% {
- -webkit-transform: scale(1.0);
- transform: scale(1.0);
- }
+ }
+ 40% {
+ -webkit-transform: scale(1.0);
+ transform: scale(1.0);
+ }
}
\ No newline at end of file
diff --git a/website/src/App.js b/website/src/App.js
index 0a00b8f..4bac8a4 100644
--- a/website/src/App.js
+++ b/website/src/App.js
@@ -1,23 +1,40 @@
-import React, {Component} from 'react';
-import logo from './logo.svg';
-import {Navbar, Nav, NavItem} from 'react-bootstrap'
-import './App.css';
+import React, {Component} from 'react'
+import logo from './logo.svg'
+import {Nav, Navbar, NavItem} from 'react-bootstrap'
+import './App.css'
const README = require('../../README.md')
const exampleName = document.location.search.replace('?ex=', '')
-const PUBLIC_URL = process.env.PUBLIC_URL || '/'
+const PUBLIC_URL = (document && document.location && document.location.host === 'localhost:3000') ? process.env.PUBLIC_URL || '/' : 'https://edtoken.github.io/redux-tide'
-const exampleComponents = {
- 'blog': require('./blog'),
- 'different-entity-id': require('./different-entity-id'),
- 'merged-actions-data': require('./merged-actions-data')
-}
+const EXAMPLES = [
+ {
+ 'title': 'Blog example',
+ 'path': 'blog',
+ 'component': require('./blog')
+ },
+ {
+ 'title': 'Different entity id',
+ 'path': 'different-entity-id',
+ 'component': require('./different-entity-id')
+ },
+ {
+ 'title': 'Merged actions data',
+ 'path': 'merged-actions-data',
+ 'component': require('./merged-actions-data')
+ },
+ {
+ 'title': 'Delete entity from state',
+ 'path': 'delete-entity-from-state',
+ 'component': require('./delete-entity-from-state')
+ }
+]
class App extends Component {
render() {
- const ExampleComponent = exampleName && exampleComponents[exampleName] ? exampleComponents[exampleName].default : undefined
+ const ExampleComponent = exampleName ? EXAMPLES.find(item => item.path === exampleName).component.default : undefined
return (
@@ -30,11 +47,11 @@ class App extends Component {
Star
+ aria-label="Star @edtoken/redux-tide on GitHub">Star
@@ -53,15 +70,12 @@ class App extends Component {
Index
-
- Blog example
-
-
- Different entity id
-
-
- Merged actions data
-
+ {EXAMPLES.map((item, num) => {
+ return
+ {item.title}
+
+ })}
@@ -87,8 +101,8 @@ class App extends Component {
}
- );
+ )
}
}
-export default App;
+export default App
diff --git a/website/src/App.test.js b/website/src/App.test.js
index b84af98..e639a62 100644
--- a/website/src/App.test.js
+++ b/website/src/App.test.js
@@ -1,8 +1,8 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import App from './App';
+import React from 'react'
+import ReactDOM from 'react-dom'
+import App from './App'
it('renders without crashing', () => {
- const div = document.createElement('div');
- ReactDOM.render( , div);
-});
+ const div = document.createElement('div')
+ ReactDOM.render( , div)
+})
diff --git a/website/src/DevTools.js b/website/src/DevTools.js
index 5459367..07457ca 100644
--- a/website/src/DevTools.js
+++ b/website/src/DevTools.js
@@ -1,4 +1,4 @@
-import React, {Component} from 'react'
+import React from 'react'
import {createDevTools} from 'redux-devtools'
import LogMonitor from 'redux-devtools-log-monitor'
import DockMonitor from 'redux-devtools-dock-monitor'
@@ -8,7 +8,7 @@ export default createDevTools(
diff --git a/website/src/RESTApi.js b/website/src/RESTApi.js
index df872e5..d4384eb 100644
--- a/website/src/RESTApi.js
+++ b/website/src/RESTApi.js
@@ -5,7 +5,7 @@ const apiInstance = axios.create({
})
const createRequest = method => {
- return function(url, params = {}, data = {}) {
+ return function (url, params = {}, data = {}) {
return apiInstance.request({
method,
url: url,
diff --git a/website/src/blog/actions.js b/website/src/blog/actions.js
index 0809914..bec1a63 100644
--- a/website/src/blog/actions.js
+++ b/website/src/blog/actions.js
@@ -1,6 +1,6 @@
-import {createAction} from "../../../src/action";
+import {createAction} from 'redux-tide'
import * as api from '../RESTApi'
-import {postsSchema} from "./schema";
+import {postsSchema} from "./schema"
/**
* Ajax axios call get all posts
diff --git a/website/src/blog/index.js b/website/src/blog/index.js
index 93c4b0d..769e6d8 100644
--- a/website/src/blog/index.js
+++ b/website/src/blog/index.js
@@ -1,15 +1,15 @@
-import React, {Component} from 'react';
-import {Provider} from 'react-redux'
-import {connect} from 'react-redux'
+import React, {Component} from 'react'
+import {connect, Provider} from 'react-redux'
import {ConnectedRouter} from 'react-router-redux'
-import {Table, Pager, Modal, Button, FormControl, ControlLabel, Alert} from 'react-bootstrap'
-import {Spinner} from "../Spinner";
+import {Alert, Button, ControlLabel, FormControl, Modal, Pager, Table} from 'react-bootstrap'
+import {Spinner} from "../Spinner"
-import DevTools from '../DevTools'
import store, {history} from './store'
-import {getAllPost, fetchPost, updatePost} from "./actions";
-import {getActionData} from "../../../src";
+
+import DevTools from '../DevTools'
+import {fetchPost, getAllPost, updatePost} from "./actions"
+import {getActionData} from 'redux-tide'
class BlogPostFormComponent extends Component {
@@ -291,7 +291,7 @@ class BlogExampleComponent extends Component {
Please look into the DevTools panel and Network requests
- You can hide DevTools , click Ctrl+H
+ You can open DevTools , click Ctrl+H
`posts/${postId}`
+)
+
+export const updatePost = createAction(
+ postsSchema,
+ api.put,
+ (postId, data) => [
+ `posts/${postId}`,
+ undefined,
+ data
+ ]
+)
+
+
+export const deletePost = createAction(
+ postsSchema,
+ api.del,
+ postId => `posts/${postId}`
+)
\ No newline at end of file
diff --git a/website/src/delete-entity-from-state/index.js b/website/src/delete-entity-from-state/index.js
new file mode 100644
index 0000000..20cbbb9
--- /dev/null
+++ b/website/src/delete-entity-from-state/index.js
@@ -0,0 +1,159 @@
+import React, {Component} from 'react'
+import {connect, Provider} from 'react-redux'
+
+import {ConnectedRouter} from 'react-router-redux'
+import {Alert} from 'react-bootstrap'
+
+import DevTools from '../DevTools'
+import store, {history} from './store'
+import {deletePost, fetchPost, updatePost} from "./actions"
+import {getMergedActionsData} from 'redux-tide'
+
+class CommonPostComponent extends Component {
+
+ componentWillMount() {
+ this.props.fetch(this.props.postId)
+ }
+
+ componentWillReceiveProps(nextProps) {
+ const prevProps = this.props
+ this.props = nextProps
+
+ if (this.props.postId && this.props.postId !== prevProps.postId) {
+ this.props.fetch(this.props.postId)
+ }
+ }
+
+ render() {
+ const {postId, payload, isFetching, hasError, errorText} = this.props
+
+ return (
+ POST ID (props)
{postId}
+
post id payload {payload ? payload.id : ''}
+
+
+
+ {isFetching &&
isFetching...
}
+
+
+
this.props.fetch(postId)}
+ className="btn btn-xs btn-primary">
+ Fetch
+
+
+
this.props.update(postId, {title: ['title', Math.random().toFixed(3)].join('-')})}
+ className="btn btn-xs btn-success">
+ Update
+
+
+
this.props.del(postId)}
+ className="btn btn-xs btn-danger">
+ Delete
+
+
+
+ {hasError &&
{errorText}
}
+
{JSON.stringify(payload, null, 2)}
+
)
+ }
+}
+
+const CommonPost = connect(
+ (state, props) => getMergedActionsData(
+ fetchPost.withPrefix(props.postId),
+ updatePost.withPrefix(props.postId),
+ deletePost.withPrefix(props.postId)
+ ),
+ (dispatch) => ({
+ del: postId => dispatch(deletePost.withPrefix(postId)(postId)),
+ fetch: postId => dispatch(fetchPost.withPrefix(postId)(postId)),
+ update: (postId, data) => dispatch(updatePost.withPrefix(postId)(postId, data))
+ })
+)(CommonPostComponent)
+
+class PostsListComponent extends Component {
+
+ render() {
+ return (
+
Posts List
+ )
+ }
+}
+
+const PostsList = connect(
+ (state, props) => ({}),
+ (dispatch) => ({})
+)(PostsListComponent)
+
+class PostsTableComponent extends Component {
+ render() {
+ return (
+
Posts Table
+ )
+ }
+}
+
+const PostsTable = connect(
+ (state, props) => ({}),
+ (dispatch) => ({})
+)(PostsTableComponent)
+
+class DeleteTntityFromStateExampleComponent extends Component {
+
+ constructor(props) {
+ super(props)
+ }
+
+ render() {
+
+ return (
+
Delete Entity from state
+
Source code source
+
+
+
+ Demonstrate how to use `dispatch(action.delete())` method
+
+
+
+
+
With delete It's correct
+
+
+
+
+
+
+
+
Without delete It's no correct
+
+
+
+
+
+
+
+
)
+ }
+}
+
+export default class MergedActionsDataComponentWrapper extends Component {
+
+ render() {
+ return ()
+ }
+}
\ No newline at end of file
diff --git a/website/src/delete-entity-from-state/reducer.js b/website/src/delete-entity-from-state/reducer.js
new file mode 100644
index 0000000..b9abc22
--- /dev/null
+++ b/website/src/delete-entity-from-state/reducer.js
@@ -0,0 +1,13 @@
+/**
+ *
+ * Common reducer with your data
+ *
+ */
+const defaultState = {
+ NODE_ENV: process.env.NODE_ENV
+}
+
+export const customReducer = (state = defaultState, action) => {
+
+ return state
+}
\ No newline at end of file
diff --git a/website/src/delete-entity-from-state/schema.js b/website/src/delete-entity-from-state/schema.js
new file mode 100644
index 0000000..a8130ed
--- /dev/null
+++ b/website/src/delete-entity-from-state/schema.js
@@ -0,0 +1,26 @@
+import {schema} from 'normalizr'
+
+const profileSchema = new schema.Entity('profile')
+const commentsSchema = new schema.Entity('comments')
+const postsSchema = new schema.Entity('posts')
+
+postsSchema.define({
+ // author: profileSchema,
+ // comments: [commentsSchema]
+})
+
+commentsSchema.define({
+ // postId: postsSchema
+})
+
+export {
+ profileSchema,
+ commentsSchema,
+ postsSchema
+}
+
+export const appSchema = {
+ profileSchema,
+ commentsSchema,
+ postsSchema
+}
\ No newline at end of file
diff --git a/website/src/delete-entity-from-state/store.js b/website/src/delete-entity-from-state/store.js
new file mode 100644
index 0000000..c995c07
--- /dev/null
+++ b/website/src/delete-entity-from-state/store.js
@@ -0,0 +1,39 @@
+import {applyMiddleware, combineReducers, compose, createStore} from 'redux'
+import {routerMiddleware} from 'react-router-redux'
+import {denormalize} from 'normalizr'
+import thunk from 'redux-thunk'
+import createHistory from 'history/createBrowserHistory'
+import {createReducers, setDefaultResponseMapper, setDenormalize} from 'redux-tide'
+import DevTools from '../DevTools'
+import {customReducer} from './reducer'
+import {appSchema} from './schema'
+
+setDefaultResponseMapper((resp) => {
+ return resp.data
+})
+
+setDenormalize(denormalize)
+
+export const history = createHistory()
+
+const rootInitialState = {}
+const enhancers = []
+const middleware = [
+ thunk,
+ routerMiddleware(history)
+]
+
+enhancers.push(DevTools.instrument())
+
+const composedEnhancers = compose(
+ applyMiddleware(...middleware),
+ ...enhancers
+)
+export default createStore(
+ combineReducers({
+ custom: customReducer,
+ ...createReducers(...appSchema)
+ }),
+ rootInitialState,
+ composedEnhancers
+)
\ No newline at end of file
diff --git a/website/src/different-entity-id/actions.js b/website/src/different-entity-id/actions.js
index ec4e120..6ecbca2 100644
--- a/website/src/different-entity-id/actions.js
+++ b/website/src/different-entity-id/actions.js
@@ -1,6 +1,6 @@
-import {createAction} from "../../../src/action";
+import {createAction} from 'redux-tide'
import * as api from '../RESTApi'
-import {postsSchema} from "./schema";
+import {postsSchema} from "./schema"
/**
diff --git a/website/src/different-entity-id/index.js b/website/src/different-entity-id/index.js
index 61b64be..604346e 100644
--- a/website/src/different-entity-id/index.js
+++ b/website/src/different-entity-id/index.js
@@ -1,25 +1,23 @@
-import React, {Component} from 'react';
-import {Provider} from 'react-redux'
-import {connect} from 'react-redux'
+import React, {Component} from 'react'
+import {connect, Provider} from 'react-redux'
import {ConnectedRouter} from 'react-router-redux'
-import {Table, Pager, ProgressBar, Modal, Button, FormControl, ControlLabel, Alert} from 'react-bootstrap'
+import {Alert} from 'react-bootstrap'
import DevTools from '../DevTools'
import store, {history} from './store'
-import {fetchPost, fetchSinglePost, updatePost, updateSinglePost} from "./actions";
-import {getActionData} from "../../../src";
+import {fetchPost, fetchSinglePost, updatePost, updateSinglePost} from "./actions"
+import {getActionData} from 'redux-tide'
class CommonPostComponent extends Component {
componentWillMount() {
- console.log('fetch', this.props.postId)
this.props.fetch(this.props.postId)
}
componentWillReceiveProps(nextProps) {
// it's need only for SinglePostCorrectComponent
- const prevProps = this.props;
+ const prevProps = this.props
this.props = nextProps
if (this.props.postId && this.props.postId !== prevProps.postId) {
@@ -62,8 +60,8 @@ class CommonPostComponent extends Component {
const PostCorrectComponent = connect(
(state, props) => getActionData(fetchPost.withPrefix(props.postId)),
dispatch => ({
- fetch: (postId) => dispatch(fetchPost.withPrefix(postId)(postId)),
- update: (postId, data) => dispatch(updatePost.withPrefix(postId)(postId, data))
+ fetch: postId => dispatch(fetchPost.withPrefix(postId)(postId)),
+ update: (postId, data) => dispatch(updatePost.withPrefix(postId)(postId, data)),
})
)(CommonPostComponent)
@@ -79,8 +77,8 @@ const PostIncorrectComponent = connect(
const SinglePostCorrectComponent = connect(
state => getActionData(fetchSinglePost),
dispatch => ({
- fetch: (postId) => dispatch(fetchSinglePost(postId)),
- update: (postId, data) => (dispatch(updateSinglePost(postId, data)))
+ fetch: postId => dispatch(fetchSinglePost(postId)),
+ update: (postId, data) => dispatch(updateSinglePost(postId, data))
})
)(CommonPostComponent)
@@ -113,7 +111,8 @@ class DifferentEntityIdExampleComponent extends Component {
return (
Different entity Id
-
Source code source
+
Source code source
Demonstrate how to use `.withPrefix`, `.withName`, `.clone` methods
@@ -140,7 +139,8 @@ class DifferentEntityIdExampleComponent extends Component {
If you are have 1 component to 1 action
you can use without withPrefix method, it's not required
- Please change postId from input to 2 , Then click update and look correct-post-2
+ Please change postId from input to 2 , Then click update
+ and look correct-post-2
, document.getElementById('root'));
-// registerServiceWorker();
+ReactDOM.render( , document.getElementById('root'))
diff --git a/website/src/logo.svg b/website/src/logo.svg
index 6b60c10..4ec91df 100644
--- a/website/src/logo.svg
+++ b/website/src/logo.svg
@@ -1,6 +1,7 @@
-
+
diff --git a/website/src/merged-actions-data/actions.js b/website/src/merged-actions-data/actions.js
index ff8702f..2c1358e 100644
--- a/website/src/merged-actions-data/actions.js
+++ b/website/src/merged-actions-data/actions.js
@@ -1,6 +1,6 @@
-import {createAction} from "../../../src/action";
+import {createAction} from 'redux-tide'
import * as api from '../RESTApi'
-import {postsSchema} from "./schema";
+import {postsSchema} from "./schema"
/**
diff --git a/website/src/merged-actions-data/index.js b/website/src/merged-actions-data/index.js
index 168842b..2aa2884 100644
--- a/website/src/merged-actions-data/index.js
+++ b/website/src/merged-actions-data/index.js
@@ -1,14 +1,13 @@
-import React, {Component} from 'react';
-import {Provider} from 'react-redux'
-import {connect} from 'react-redux'
+import React, {Component} from 'react'
+import {connect, Provider} from 'react-redux'
import {ConnectedRouter} from 'react-router-redux'
-import {Table, Pager, ProgressBar, Modal, Button, FormControl, ControlLabel, Alert} from 'react-bootstrap'
+import {Alert} from 'react-bootstrap'
import DevTools from '../DevTools'
import store, {history} from './store'
-import {fetchPost, fetchSinglePost, updatePost, updateSinglePost} from "./actions";
-import {getActionData, getMergedActionsData} from "../../../src";
+import {fetchPost, fetchSinglePost, updatePost, updateSinglePost} from "./actions"
+import {getActionData, getMergedActionsData} from "../../../src"
class CommonPostComponent extends Component {
@@ -97,7 +96,8 @@ class DifferentEntityIdExampleComponent extends Component {
return (
Merged Actions Data
-
Source code source
+
Source code source
Demonstrate how to use `getMergedActionsData` selector
diff --git a/website/src/merged-actions-data/store.js b/website/src/merged-actions-data/store.js
index 806c7dc..c995c07 100644
--- a/website/src/merged-actions-data/store.js
+++ b/website/src/merged-actions-data/store.js
@@ -1,9 +1,9 @@
import {applyMiddleware, combineReducers, compose, createStore} from 'redux'
import {routerMiddleware} from 'react-router-redux'
-import {denormalize} from 'normalizr';
+import {denormalize} from 'normalizr'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
-import {createReducers, setDefaultResponseMapper, setDenormalize} from '../../../src/index';
+import {createReducers, setDefaultResponseMapper, setDenormalize} from 'redux-tide'
import DevTools from '../DevTools'
import {customReducer} from './reducer'
import {appSchema} from './schema'
diff --git a/website/src/registerServiceWorker.js b/website/src/registerServiceWorker.js
index 12542ba..9612a6c 100644
--- a/website/src/registerServiceWorker.js
+++ b/website/src/registerServiceWorker.js
@@ -10,36 +10,36 @@
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
- // [::1] is the IPv6 localhost address.
- window.location.hostname === '[::1]' ||
- // 127.0.0.1/8 is considered localhost for IPv4.
- window.location.hostname.match(
- /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
- )
-);
+ // [::1] is the IPv6 localhost address.
+ window.location.hostname === '[::1]' ||
+ // 127.0.0.1/8 is considered localhost for IPv4.
+ window.location.hostname.match(
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ )
+)
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
- const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
+ const publicUrl = new URL(process.env.PUBLIC_URL, window.location)
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
- return;
+ return
}
window.addEventListener('load', () => {
- const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+ const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
- checkValidServiceWorker(swUrl);
+ checkValidServiceWorker(swUrl)
} else {
// Is not local host. Just register service worker
- registerValidSW(swUrl);
+ registerValidSW(swUrl)
}
- });
+ })
}
}
@@ -48,7 +48,7 @@ function registerValidSW(swUrl) {
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
- const installingWorker = registration.installing;
+ const installingWorker = registration.installing
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
@@ -56,20 +56,20 @@ function registerValidSW(swUrl) {
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
- console.log('New content is available; please refresh.');
+ console.log('New content is available; please refresh.')
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
- console.log('Content is cached for offline use.');
+ console.log('Content is cached for offline use.')
}
}
- };
- };
+ }
+ }
})
.catch(error => {
- console.error('Error during service worker registration:', error);
- });
+ console.error('Error during service worker registration:', error)
+ })
}
function checkValidServiceWorker(swUrl) {
@@ -84,25 +84,25 @@ function checkValidServiceWorker(swUrl) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
- window.location.reload();
- });
- });
+ window.location.reload()
+ })
+ })
} else {
// Service worker found. Proceed as normal.
- registerValidSW(swUrl);
+ registerValidSW(swUrl)
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
- );
- });
+ )
+ })
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
- registration.unregister();
- });
+ registration.unregister()
+ })
}
}