├── .eslintignore ├── codecov.yml ├── test ├── .eslintrc ├── babel-transformer.jest.js ├── react │ ├── 16.4 │ │ └── package.json │ ├── 16.5 │ │ ├── package.json │ │ └── package-lock.json │ ├── 16.6 │ │ └── package.json │ └── 16.8 │ │ └── package.json ├── utils │ ├── isPlainObject.spec.js │ ├── wrapActionCreators.spec.js │ └── shallowEqual.spec.js ├── run-tests.js ├── install-test-deps.js ├── integration │ └── server-rendering.spec.js └── components │ ├── connectAdvanced.spec.js │ └── Provider.spec.js ├── .prettierrc ├── website ├── static │ ├── img │ │ ├── favicon │ │ │ └── favicon.ico │ │ ├── redux-logo-twitter.png │ │ ├── redux-logo-landscape.png │ │ ├── noun_Check_1870817.svg │ │ ├── external-link-square-alt-solid.svg │ │ ├── redux.svg │ │ ├── redux_white.svg │ │ ├── github-brands.svg │ │ ├── noun_Box_1664404.svg │ │ ├── noun_Rocket_1245262.svg │ │ └── noun_Certificate_1945625.svg │ ├── scripts │ │ ├── sidebarScroll.js │ │ └── codeblock.js │ └── css │ │ ├── codeblock.css │ │ ├── 404.css │ │ └── custom.css ├── package.json ├── _redirects ├── sidebars.json ├── pages │ └── en │ │ ├── 404.js │ │ └── index.js ├── siteConfig.js ├── core │ └── Footer.js └── README.md ├── CHANGELOG.md ├── src ├── components │ ├── Context.js │ ├── Provider.js │ └── connectAdvanced.js ├── utils │ ├── wrapActionCreators.js │ ├── readContext.js │ ├── verifyPlainObject.js │ ├── isPlainObject.js │ ├── warning.js │ ├── shallowEqual.js │ └── Subscription.js ├── index.js └── connect │ ├── mapStateToProps.js │ ├── verifySubselectors.js │ ├── mapDispatchToProps.js │ ├── mergeProps.js │ ├── wrapMapToProps.js │ ├── connect.js │ └── selectorFactory.js ├── .travis.yml ├── .gitignore ├── .github └── ISSUE_TEMPLATE │ ├── ---support-usage-question.md │ └── ---bug-report.md ├── .babelrc.js ├── docs ├── README.md ├── introduction │ ├── quick-start.md │ └── why-use-react-redux.md ├── api │ ├── Provider.md │ └── connect-advanced.md ├── troubleshooting.md └── using-react-redux │ ├── accessing-store.md │ ├── connect-extracting-data-with-mapStateToProps.md │ └── connect-dispatching-actions-with-mapDispatchToProps.md ├── .eslintrc ├── LICENSE.md ├── CODE_OF_CONDUCT.md ├── rollup.config.js ├── context.md ├── package.json ├── CONTRIBUTING.md └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | node_modules -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2 5 | } 6 | -------------------------------------------------------------------------------- /website/static/img/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salvoravida/react-redux-fork/HEAD/website/static/img/favicon/favicon.ico -------------------------------------------------------------------------------- /website/static/img/redux-logo-twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salvoravida/react-redux-fork/HEAD/website/static/img/redux-logo-twitter.png -------------------------------------------------------------------------------- /website/static/img/redux-logo-landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/salvoravida/react-redux-fork/HEAD/website/static/img/redux-logo-landscape.png -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | v6.5.2 2 | *fix missing exports 3 | 4 | v6.5.1 5 | *fix warning on invalid mStP or mDtP 6 | 7 | v6.5.0 8 | *first react-redux-fork release 9 | -------------------------------------------------------------------------------- /src/components/Context.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export const ReactReduxContext = React.createContext(null) 4 | 5 | export default ReactReduxContext 6 | -------------------------------------------------------------------------------- /src/utils/wrapActionCreators.js: -------------------------------------------------------------------------------- 1 | import { bindActionCreators } from 'redux' 2 | 3 | export default function wrapActionCreators(actionCreators) { 4 | return dispatch => bindActionCreators(actionCreators, dispatch) 5 | } 6 | -------------------------------------------------------------------------------- /test/babel-transformer.jest.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { createTransformer } = require('babel-jest') 3 | 4 | module.exports = createTransformer({ 5 | configFile: path.resolve(__dirname, '../.babelrc.js') 6 | }) 7 | -------------------------------------------------------------------------------- /src/utils/readContext.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export const unstable_readContext = Context => { 4 | const s = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED 5 | return s.ReactCurrentDispatcher.current.readContext(Context) 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | env: 5 | matrix: 6 | - REACT=16.4 7 | - REACT=16.5 8 | - REACT=16.6 9 | - REACT=16.8 10 | sudo: false 11 | script: 12 | - npm test 13 | after_success: 14 | - npm run coverage 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Provider from './components/Provider' 2 | import connectAdvanced from './components/connectAdvanced' 3 | import { ReactReduxContext } from './components/Context' 4 | import connect from './connect/connect' 5 | 6 | export { Provider, connectAdvanced, ReactReduxContext, connect } 7 | -------------------------------------------------------------------------------- /test/react/16.4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "create-react-class": "^15.6.3", 5 | "react": "16.4", 6 | "react-dom": "16.4" 7 | }, 8 | "dependencies": { 9 | "jest-dom": "^1.12.0", 10 | "react-testing-library": "^5.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/react/16.5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "create-react-class": "^15.6.3", 5 | "react": "16.5", 6 | "react-dom": "16.5" 7 | }, 8 | "dependencies": { 9 | "jest-dom": "^1.12.0", 10 | "react-testing-library": "^5.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/react/16.6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "create-react-class": "^15.6.3", 5 | "react": "16.6", 6 | "react-dom": "16.6" 7 | }, 8 | "dependencies": { 9 | "jest-dom": "^1.12.0", 10 | "react-testing-library": "^5.0.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/react/16.8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "create-react-class": "^15.6.3", 5 | "react": "16.8", 6 | "react-dom": "16.8" 7 | }, 8 | "dependencies": { 9 | "jest-dom": "^3.1.2", 10 | "react-testing-library": "^5.9.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /website/static/img/noun_Check_1870817.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/verifyPlainObject.js: -------------------------------------------------------------------------------- 1 | import isPlainObject from './isPlainObject' 2 | import warning from './warning' 3 | 4 | export default function verifyPlainObject(value, displayName, methodName) { 5 | if (!isPlainObject(value)) { 6 | warning( 7 | `${methodName}() in ${displayName} must return a plain object. Instead received ${value}.` 8 | ) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "docusaurus-start", 4 | "build": "docusaurus-build", 5 | "publish-gh-pages": "docusaurus-publish", 6 | "write-translations": "docusaurus-write-translations", 7 | "version": "docusaurus-version", 8 | "rename-version": "docusaurus-rename-version" 9 | }, 10 | "devDependencies": { 11 | "docusaurus": "^1.6.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | dist 5 | lib 6 | .nyc_output 7 | coverage 8 | es 9 | test/**/lcov.info 10 | test/**/lcov-report 11 | test/react/*/test/**/*.spec.js 12 | test/react/**/src 13 | test/jest-config.json 14 | lcov.info 15 | 16 | lib/core/metadata.js 17 | lib/core/MetadataBlog.js 18 | 19 | website/translated_docs 20 | website/build/ 21 | website/yarn.lock 22 | website/node_modules 23 | website/i18n/* 24 | .idea/ 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---support-usage-question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F914 Support/Usage Question" 3 | about: For usage questions, please use Stack Overflow or Reactiflux! 4 | 5 | --- 6 | 7 | This is a bug tracker, not a support system. For usage questions, please use Stack Overflow or Reactiflux where there are a lot more people ready to help you out. Thanks! 8 | 9 | https://stackoverflow.com/questions/tagged/redux 10 | https://www.reactiflux.com/ 11 | -------------------------------------------------------------------------------- /website/_redirects: -------------------------------------------------------------------------------- 1 | /docs/using-react-redux/connect-extracting-data-with-mapStateToProps /using-react-redux/connect-mapstate 2 | /docs/using-react-redux/connect-extracting-data-with-mapstatetoprops /using-react-redux/connect-mapstate 3 | /docs/using-react-redux/connect-dispatching-actions-with-mapDispatchToProps /using-react-redux/connect-mapdispatch 4 | /docs/using-react-redux/connect-dispatching-actions-with-mapdispatchtoprops /using-react-redux/connect-mapdispatch 5 | 6 | /docs/* /:splat 7 | -------------------------------------------------------------------------------- /.babelrc.js: -------------------------------------------------------------------------------- 1 | const { NODE_ENV, BABEL_ENV } = process.env 2 | const cjs = NODE_ENV === 'test' || BABEL_ENV === 'commonjs' 3 | const loose = true 4 | 5 | module.exports = { 6 | presets: [['@babel/env', { loose, modules: false }]], 7 | plugins: [ 8 | ['@babel/proposal-decorators', { legacy: true }], 9 | ['@babel/proposal-object-rest-spread', { loose }], 10 | '@babel/transform-react-jsx', 11 | cjs && ['@babel/transform-modules-commonjs', { loose }], 12 | ['@babel/transform-runtime', { useESModules: !cjs }], 13 | ].filter(Boolean), 14 | } 15 | -------------------------------------------------------------------------------- /src/connect/mapStateToProps.js: -------------------------------------------------------------------------------- 1 | import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps' 2 | 3 | export function whenMapStateToPropsIsFunction(mapStateToProps) { 4 | return typeof mapStateToProps === 'function' 5 | ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps') 6 | : undefined 7 | } 8 | 9 | export function whenMapStateToPropsIsMissing(mapStateToProps) { 10 | return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined 11 | } 12 | 13 | export default [whenMapStateToPropsIsFunction, whenMapStateToPropsIsMissing] 14 | -------------------------------------------------------------------------------- /src/utils/isPlainObject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {any} obj The object to inspect. 3 | * @returns {boolean} True if the argument appears to be a plain object. 4 | */ 5 | export default function isPlainObject(obj) { 6 | if (typeof obj !== 'object' || obj === null) return false 7 | 8 | let proto = Object.getPrototypeOf(obj) 9 | if (proto === null) return true 10 | 11 | let baseProto = proto 12 | while (Object.getPrototypeOf(baseProto) !== null) { 13 | baseProto = Object.getPrototypeOf(baseProto) 14 | } 15 | 16 | return proto === baseProto 17 | } 18 | -------------------------------------------------------------------------------- /website/sidebars.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": { 3 | "Introduction": [ 4 | "introduction/quick-start", 5 | "introduction/basic-tutorial", 6 | "introduction/why-use-react-redux" 7 | ], 8 | "Using React Redux": [ 9 | "using-react-redux/connect-mapstate", 10 | "using-react-redux/connect-mapdispatch", 11 | "using-react-redux/accessing-store" 12 | ], 13 | "API Reference": [ 14 | "api/connect", 15 | "api/provider", 16 | "api/connect-advanced" 17 | ], 18 | "Guides": [ 19 | "troubleshooting" 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /website/static/img/external-link-square-alt-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Table of Contents 2 | 3 | - Introduction 4 | - [Quick Start: adding React Redux to a React todo app](./introduction/quick-start.md) 5 | - [Basic Tutorial](./introduction/basic-tutorial.md) 6 | - Using React Redux 7 | - [Connect: Extracting Data with `mapStateToProps`](./using-react-redux/connect-extracting-data-with-mapStateToProps.md) 8 | - API 9 | - [``](./api/Provider.md) 10 | - [`connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])`](./api/connect.md) 11 | - [`connectAdvanced(selectorFactory, [connectOptions])`](./api/connect-advanced.md) 12 | - [Troubleshooting](troubleshooting.md#troubleshooting) 13 | -------------------------------------------------------------------------------- /website/static/scripts/sidebarScroll.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', () => { 2 | // Find the active nav item in the sidebar 3 | const item = document.getElementsByClassName('navListItemActive')[0]; 4 | if (!item) { return; } 5 | const bounding = item.getBoundingClientRect(); 6 | if ( 7 | bounding.top >= 0 && 8 | bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) 9 | ) { 10 | // Already visible. Do nothing. 11 | } else { 12 | // Not visible. Scroll sidebar. 13 | item.scrollIntoView({block: 'center', inline: 'nearest'}); 14 | document.body.scrollTop = document.documentElement.scrollTop = 0; 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /website/static/css/codeblock.css: -------------------------------------------------------------------------------- 1 | /* "Copy" code block button */ 2 | pre { 3 | position: relative; 4 | } 5 | 6 | pre .btnIcon { 7 | position: absolute; 8 | top: 4px; 9 | z-index: 2; 10 | cursor: pointer; 11 | border: 1px solid transparent; 12 | padding: 0; 13 | color: #fff; 14 | background-color: transparent; 15 | height: 30px; 16 | transition: all .25s ease-out; 17 | } 18 | 19 | pre .btnIcon:hover { 20 | text-decoration: none; 21 | } 22 | 23 | .btnIcon__body { 24 | align-items: center; 25 | display: flex; 26 | } 27 | 28 | .btnIcon svg { 29 | fill: currentColor; 30 | margin-right: .4em; 31 | } 32 | 33 | .btnIcon__label { 34 | font-size: 11px; 35 | } 36 | 37 | .btnClipboard { 38 | right: 10px; 39 | } -------------------------------------------------------------------------------- /src/utils/warning.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Prints a warning in the console if it exists. 3 | * 4 | * @param {String} message The warning message. 5 | * @returns {void} 6 | */ 7 | export default function warning(message) { 8 | /* eslint-disable no-console */ 9 | if (typeof console !== 'undefined' && typeof console.error === 'function') { 10 | console.error(message) 11 | } 12 | /* eslint-enable no-console */ 13 | try { 14 | // This error was thrown as a convenience so that if you enable 15 | // "break on all exceptions" in your console, 16 | // it would pause the execution at this line. 17 | throw new Error(message) 18 | /* eslint-disable no-empty */ 19 | } catch (e) {} 20 | /* eslint-enable no-empty */ 21 | } 22 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "eslint:recommended", 5 | "plugin:import/recommended", 6 | "plugin:react/recommended", 7 | "plugin:prettier/recommended" 8 | ], 9 | "parserOptions": { 10 | "ecmaVersion": 6, 11 | "sourceType": "module", 12 | "ecmaFeatures": { 13 | "jsx": true, 14 | "experimentalObjectRestSpread": true 15 | } 16 | }, 17 | "env": { 18 | "browser": true, 19 | "mocha": true, 20 | "node": true 21 | }, 22 | "rules": { 23 | "valid-jsdoc": 2, 24 | "react/jsx-uses-react": 1, 25 | "react/jsx-no-undef": 2, 26 | "react/jsx-wrap-multilines": 2, 27 | "react/no-string-refs": 0 28 | }, 29 | "plugins": [ 30 | "import", 31 | "react" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /website/static/css/404.css: -------------------------------------------------------------------------------- 1 | .error-page .error-message-container { 2 | margin-left: auto; 3 | margin-right: auto; 4 | padding-top: 40px; 5 | max-width: 1400px; 6 | width: 87%; 7 | } 8 | .error-page .error-message { 9 | min-height: 90vh; 10 | background: white; 11 | } 12 | .error-page .error-message span { 13 | color: #764ABC; 14 | font-size: 8.8em; 15 | font-weight: 700; 16 | display: inline-block; 17 | margin-top: 10vh; 18 | text-align: center; 19 | display: block; 20 | } 21 | .error-page .error-message p { 22 | color: black; 23 | margin-top: 50px; 24 | font-size: 1.6em; 25 | text-align: center; 26 | } 27 | 28 | .error-page .error-message a { 29 | margin-bottom: 50px; 30 | font-size: 1.6em; 31 | text-align: center; 32 | display: block; 33 | text-decoration: underline; 34 | } 35 | -------------------------------------------------------------------------------- /src/utils/shallowEqual.js: -------------------------------------------------------------------------------- 1 | const hasOwn = Object.prototype.hasOwnProperty 2 | 3 | function is(x, y) { 4 | if (x === y) { 5 | return x !== 0 || y !== 0 || 1 / x === 1 / y 6 | } else { 7 | return x !== x && y !== y 8 | } 9 | } 10 | 11 | export default function shallowEqual(objA, objB) { 12 | if (is(objA, objB)) return true 13 | 14 | if ( 15 | typeof objA !== 'object' || 16 | objA === null || 17 | typeof objB !== 'object' || 18 | objB === null 19 | ) { 20 | return false 21 | } 22 | 23 | const keysA = Object.keys(objA) 24 | const keysB = Object.keys(objB) 25 | 26 | if (keysA.length !== keysB.length) return false 27 | 28 | for (let i = 0; i < keysA.length; i++) { 29 | if (!hasOwn.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { 30 | return false 31 | } 32 | } 33 | 34 | return true 35 | } 36 | -------------------------------------------------------------------------------- /test/utils/isPlainObject.spec.js: -------------------------------------------------------------------------------- 1 | import isPlainObject from '../../src/utils/isPlainObject' 2 | import vm from 'vm' 3 | 4 | describe('isPlainObject', () => { 5 | it('returns true only if plain object', () => { 6 | function Test() { 7 | this.prop = 1 8 | } 9 | 10 | const sandbox = { fromAnotherRealm: false } 11 | vm.runInNewContext('fromAnotherRealm = {}', sandbox) 12 | 13 | expect(isPlainObject(sandbox.fromAnotherRealm)).toBe(true) 14 | expect(isPlainObject(new Test())).toBe(false) 15 | expect(isPlainObject(new Date())).toBe(false) 16 | expect(isPlainObject([1, 2, 3])).toBe(false) 17 | expect(isPlainObject(null)).toBe(false) 18 | expect(isPlainObject()).toBe(false) 19 | expect(isPlainObject({ x: 1, y: 2 })).toBe(true) 20 | expect(isPlainObject(Object.create(null))).toBe(true) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /src/connect/verifySubselectors.js: -------------------------------------------------------------------------------- 1 | import warning from '../utils/warning' 2 | 3 | function verify(selector, methodName, displayName) { 4 | if (!selector) { 5 | throw new Error(`Unexpected value for ${methodName} in ${displayName}.`) 6 | } else if ( 7 | methodName === 'mapStateToProps' || 8 | methodName === 'mapDispatchToProps' 9 | ) { 10 | if (!selector.hasOwnProperty('dependsOnOwnProps')) { 11 | warning( 12 | `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.` 13 | ) 14 | } 15 | } 16 | } 17 | 18 | export default function verifySubselectors( 19 | mapStateToProps, 20 | mapDispatchToProps, 21 | mergeProps, 22 | displayName 23 | ) { 24 | verify(mapStateToProps, 'mapStateToProps', displayName) 25 | verify(mapDispatchToProps, 'mapDispatchToProps', displayName) 26 | verify(mergeProps, 'mergeProps', displayName) 27 | } 28 | -------------------------------------------------------------------------------- /test/utils/wrapActionCreators.spec.js: -------------------------------------------------------------------------------- 1 | import wrapActionCreators from '../../src/utils/wrapActionCreators' 2 | 3 | describe('Utils', () => { 4 | describe('wrapActionCreators', () => { 5 | it('should return a function that wraps argument in a call to bindActionCreators', () => { 6 | function dispatch(action) { 7 | return { 8 | dispatched: action 9 | } 10 | } 11 | 12 | const actionResult = { an: 'action' } 13 | 14 | const actionCreators = { 15 | action: () => actionResult 16 | } 17 | 18 | const wrapped = wrapActionCreators(actionCreators) 19 | expect(wrapped).toBeInstanceOf(Function) 20 | expect(() => wrapped(dispatch)).not.toThrow() 21 | expect(() => wrapped().action()).toThrow() 22 | 23 | const bound = wrapped(dispatch) 24 | expect(bound.action).not.toThrow() 25 | expect(bound.action().dispatched).toBe(actionResult) 26 | }) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /src/connect/mapDispatchToProps.js: -------------------------------------------------------------------------------- 1 | import { bindActionCreators } from 'redux' 2 | import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps' 3 | 4 | export function whenMapDispatchToPropsIsFunction(mapDispatchToProps) { 5 | return typeof mapDispatchToProps === 'function' 6 | ? wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps') 7 | : undefined 8 | } 9 | 10 | export function whenMapDispatchToPropsIsMissing(mapDispatchToProps) { 11 | return !mapDispatchToProps 12 | ? wrapMapToPropsConstant(dispatch => ({ dispatch })) 13 | : undefined 14 | } 15 | 16 | export function whenMapDispatchToPropsIsObject(mapDispatchToProps) { 17 | return mapDispatchToProps && typeof mapDispatchToProps === 'object' 18 | ? wrapMapToPropsConstant(dispatch => 19 | bindActionCreators(mapDispatchToProps, dispatch) 20 | ) 21 | : undefined 22 | } 23 | 24 | export default [ 25 | whenMapDispatchToPropsIsFunction, 26 | whenMapDispatchToPropsIsMissing, 27 | whenMapDispatchToPropsIsObject 28 | ] 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Something isn't working correctly. 4 | 5 | --- 6 | 7 | **Do you want to request a _feature_ or report a _bug_?** 8 | 9 | (If this is a _usage question_, please **do not post it here**—post it on [Stack Overflow](http://stackoverflow.com/questions/tagged/redux) instead. If this is not a “feature” or a “bug”, or the phrase “How do I...?” applies, then it's probably a usage question.) 10 | 11 | 12 | **What is the current behavior?** 13 | 14 | 15 | 16 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to a CodeSandbox (https://codesandbox.io/s/new) or RN Snack (https://snack.expo.io/) example below:** 17 | 18 | 19 | 20 | **What is the expected behavior?** 21 | 22 | 23 | 24 | **Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using? Which browser and OS are affected by this issue? Did this work in previous versions of React Redux?** 25 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-present Dan Abramov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /website/static/img/redux.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /website/static/img/redux_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/run-tests.js: -------------------------------------------------------------------------------- 1 | const npmRun = require('npm-run') 2 | const fs = require('fs') 3 | const path = require('path') 4 | const LATEST_VERSION = '16.8' 5 | const version = process.env.REACT || LATEST_VERSION 6 | 7 | let jestConfig = { 8 | testURL: 'http://localhost', 9 | collectCoverage: true, 10 | coverageDirectory: `${__dirname}/coverage`, 11 | transform: { 12 | '.js$': `${__dirname}/babel-transformer.jest.js` 13 | } 14 | } 15 | 16 | require('./install-test-deps.js') 17 | 18 | if (version.toLowerCase() === 'all') { 19 | jestConfig = { 20 | ...jestConfig, 21 | rootDir: __dirname, 22 | // every directory has the same coverage, so we collect it only from one 23 | collectCoverageFrom: [`react/${LATEST_VERSION}/src/**.js`] 24 | } 25 | } else { 26 | jestConfig = { 27 | ...jestConfig, 28 | rootDir: `${__dirname}/react/${version}` 29 | } 30 | } 31 | 32 | const configFilePath = path.join(__dirname, 'jest-config.json') 33 | 34 | fs.writeFileSync(configFilePath, JSON.stringify(jestConfig)) 35 | 36 | const commandLine = `jest -c "${configFilePath}" ${process.argv.slice(2).join(' ')}` 37 | 38 | npmRun.execSync( 39 | commandLine, 40 | { stdio: 'inherit' } 41 | ) 42 | -------------------------------------------------------------------------------- /website/pages/en/404.js: -------------------------------------------------------------------------------- 1 | const React = require("react"); 2 | const siteConfig = require(`${process.cwd()}/siteConfig.js`); 3 | 4 | class ErrorPage extends React.Component { 5 | getTrackingScript() { 6 | if (!siteConfig.gaTrackingId) { 7 | return null; 8 | } 9 | 10 | return {__html:` 11 | ga('create', "${siteConfig.gaTrackingId}"); 12 | ga('send', { 13 | hitType: 'event', 14 | eventCategory: '404 Response', 15 | eventAction: window.location.href, 16 | eventLabel: document.referrer 17 | });` 18 | } 19 | } 20 | 21 | render() { 22 | const trackingScript = this.getTrackingScript(); 23 | 24 | return ( 25 |
26 | {trackingScript &&