diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 4008e3aa97..a32167a58a 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -1,16 +1,16 @@ ---- -name: "\U0001F41BBug report" -about: Something isn't working correctly. ---- - -**Do you want to request a _feature_ or report a _bug_?** - -(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.) - -**What is the current behavior?** - -**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.** - -**What is the expected behavior?** - -**Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?** +--- +name: "\U0001F41BBug report" +about: Something is wrong with Redux. +--- + +**Do you want to request a _feature_ or report a _bug_?** + +(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.) + +**What is the current behavior?** + +**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via https://jsfiddle.net or similar.** + +**What is the expected behavior?** + +**Which versions of Redux, and which browser and OS are affected by this issue? Did this work in previous versions of Redux?** diff --git a/.github/ISSUE_TEMPLATE/Custom.md b/.github/ISSUE_TEMPLATE/Custom.md index c74b96a213..1af4601565 100644 --- a/.github/ISSUE_TEMPLATE/Custom.md +++ b/.github/ISSUE_TEMPLATE/Custom.md @@ -1,9 +1,9 @@ ---- -name: "\U0001F914Support/Usage Question" -about: For usage questions, please use Stack Overflow or Reactiflux! ---- - -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! - -https://stackoverflow.com/questions/tagged/redux -https://www.reactiflux.com/ +--- +name: "\U0001F914Support/Usage Question" +about: For usage questions, please use Stack Overflow or Reactiflux! +--- + +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! + +https://stackoverflow.com/questions/tagged/redux +https://www.reactiflux.com/ diff --git a/.gitignore b/.gitignore index a3ab034238..cc152e1c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,8 @@ dist lib es coverage + +website/translated_docs +website/build/ +website/node_modules +website/i18n/* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3d49992cf..16b40f6446 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ Visit the [issue tracker](https://github.com/reduxjs/redux/issues) to find a lis Fork, then clone the repo: -``` +```sh git clone https://github.com/your-username/redux.git ``` @@ -44,7 +44,7 @@ git clone https://github.com/your-username/redux.git Running the `build` task will create a CommonJS module-per-module build, a ES Modules build and a UMD build. -``` +```sh npm run build ``` @@ -52,19 +52,19 @@ npm run build To only run linting: -``` +```sh npm run lint ``` To only run tests: -``` +```sh npm run test ``` To continuously watch and run tests, run the following: -``` +```sh npm run test:watch ``` @@ -84,7 +84,7 @@ When adding a new example, please adhere to the style and format of the existing To test the official Redux examples, run the following: -``` +```sh npm run examples:test ``` diff --git a/README.md b/README.md index 1e12679063..a06fc42ab8 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ It helps you write applications that behave consistently, run in different envir You can use Redux together with [React](https://reactjs.org), or with any other view library. It is tiny (2kB, including dependencies). +> **Note**: We are currently planning a rewrite of the Redux docs. Please take some time to **[fill out this survey on what content is most important in a docs site](https://docs.google.com/forms/d/e/1FAIpQLSfzIkY3fXZ8PrQKScYMK0YoEgALfAK2qQ0mOj1_ibKv2qDTuQ/viewform)**. Thanks! + [![build status](https://img.shields.io/travis/reduxjs/redux/master.svg?style=flat-square)](https://travis-ci.org/reduxjs/redux) [![npm version](https://img.shields.io/npm/v/redux.svg?style=flat-square)](https://www.npmjs.com/package/redux) [![npm downloads](https://img.shields.io/npm/dm/redux.svg?style=flat-square)](https://www.npmjs.com/package/redux) @@ -90,7 +92,7 @@ Even if you haven't used Flux or Elm, Redux only takes a few minutes to get star To install the stable version: -``` +```sh npm install --save redux ``` @@ -108,7 +110,7 @@ The Redux source code is written in ES2015 but we precompile both CommonJS and U Most likely, you'll also need [the React bindings](https://github.com/reduxjs/react-redux) and [the developer tools](https://github.com/reduxjs/redux-devtools). -``` +```sh npm install --save react-redux npm install --save-dev redux-devtools ``` @@ -215,7 +217,7 @@ The **[Building React Applications with Idiomatic Redux](https://egghead.io/cour **[Practical Redux](https://www.educative.io/collection/5687753853370368/5707702298738688/)** is a paid interactive course by Redux co-maintainer [Mark Erikson](https://twitter.com/acemarke). The course is designed to show how to apply the basic concepts of Redux to building something larger than a TodoMVC application. It includes real-world topics like: - Adding Redux to a new Create-React-App project and configuring Hot Module Replacement for faster development -- Controling your UI behavior with Redux +- Controlling your UI behavior with Redux - Using the Redux-ORM library to manage relational data in your Redux store - Building a master/detail view to display and edit data - Writing custom advanced Redux reducer logic to solve specific problems @@ -230,7 +232,7 @@ The course is based on Mark's original free **["Practical Redux" blog tutorial s Redux co-maintainer [Mark Erikson](https://twitter.com/acemarke) has put together a [**Redux Fundamentals workshop**, and slides are available here](https://blog.isquaredsoftware.com/2018/06/redux-fundamentals-workshop-slides/). They cover: - The history and purpose of Redux -- Reducers, actions, and working with a Redux store +- Reducers and actions, and working with a Redux store - Using Redux with React - Using and writing Redux middleware - Working with AJAX calls and other side effects @@ -239,14 +241,14 @@ Redux co-maintainer [Mark Erikson](https://twitter.com/acemarke) has put togethe ## Documentation -- [Introduction](http://redux.js.org/introduction/index.html) -- [Basics](http://redux.js.org/basics/index.html) -- [Advanced](http://redux.js.org/advanced/index.html) -- [Recipes](http://redux.js.org/recipes/index.html) -- [FAQ](http://redux.js.org/FAQ.html) -- [Troubleshooting](http://redux.js.org/Troubleshooting.html) -- [Glossary](http://redux.js.org/Glossary.html) -- [API Reference](http://redux.js.org/api/index.html) +- [Introduction](http://redux.js.org/introduction) +- [Basics](http://redux.js.org/basics) +- [Advanced](http://redux.js.org/advanced) +- [Recipes](http://redux.js.org/recipes) +- [FAQ](http://redux.js.org/faq) +- [Troubleshooting](http://redux.js.org/troubleshooting) +- [Glossary](http://redux.js.org/glossary) +- [API Reference](http://redux.js.org/api) For PDF, ePub, and MOBI exports for offline reading, and instructions on how to create them, please see: [paulkogel/redux-offline-docs](https://github.com/paulkogel/redux-offline-docs). @@ -260,6 +262,7 @@ Almost all examples have a corresponding CodeSandbox sandbox. This is an interac - [**Counter**](https://redux.js.org/introduction/examples#counter): [Source](https://github.com/reduxjs/redux/tree/master/examples/counter) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/counter) - [**Todos**](https://redux.js.org/introduction/examples#todos): [Source](https://github.com/reduxjs/redux/tree/master/examples/todos) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos) - [**Todos with Undo**](https://redux.js.org/introduction/examples#todos-with-undo): [Source](https://github.com/reduxjs/redux/tree/master/examples/todos-with-undo) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos-with-undo) +- [**Todos w/ Flow**](https://redux.js.org/introduction/examples#todos-flow): [Source](https://github.com/reduxjs/redux/tree/master/examples/todos-flow) - [**TodoMVC**](https://redux.js.org/introduction/examples#todomvc): [Source](https://github.com/reduxjs/redux/tree/master/examples/todomvc) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todomvc) - [**Shopping Cart**](https://redux.js.org/introduction/examples#shopping-cart): [Source](https://github.com/reduxjs/redux/tree/master/examples/shopping-cart) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/shopping-cart) - [**Tree View**](https://redux.js.org/introduction/examples#tree-view): [Source](https://github.com/reduxjs/redux/tree/master/examples/tree-view) | [Sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/tree-view) diff --git a/docs/FAQ.md b/docs/FAQ.md index 09784a69b6..9b649503c3 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -1,67 +1,74 @@ +--- +id: faq +title: FAQ Index +sidebar_label: FAQ Index +hide_title: true +--- + # Redux FAQ ## Table of Contents - **General** - - [When should I learn Redux?](/docs/faq/General.md#when-should-i-learn-redux) - - [When should I use Redux?](/docs/faq/General.md#when-should-i-use-redux) - - [Can Redux only be used with React?](/docs/faq/General.md#can-redux-only-be-used-with-react) - - [Do I need to have a particular build tool to use Redux?](/docs/faq/General.md#do-i-need-to-have-a-particular-build-tool-to-use-redux) + - [When should I learn Redux?](faq/General.md#when-should-i-learn-redux) + - [When should I use Redux?](faq/General.md#when-should-i-use-redux) + - [Can Redux only be used with React?](faq/General.md#can-redux-only-be-used-with-react) + - [Do I need to have a particular build tool to use Redux?](faq/General.md#do-i-need-to-have-a-particular-build-tool-to-use-redux) - **Reducers** - - [How do I share state between two reducers? Do I have to use combineReducers?](/docs/faq/Reducers.md#how-do-i-share-state-between-two-reducers-do-i-have-to-use-combinereducers) - - [Do I have to use the switch statement to handle actions?](/docs/faq/Reducers.md#do-i-have-to-use-the-switch-statement-to-handle-actions) + - [How do I share state between two reducers? Do I have to use combineReducers?](faq/Reducers.md#how-do-i-share-state-between-two-reducers-do-i-have-to-use-combinereducers) + - [Do I have to use the switch statement to handle actions?](faq/Reducers.md#do-i-have-to-use-the-switch-statement-to-handle-actions) - **Organizing State** - - [Do I have to put all my state into Redux? Should I ever use React's setState()?](/docs/faq/OrganizingState.md#do-i-have-to-put-all-my-state-into-redux-should-i-ever-use-reacts-setstate) - - [Can I put functions, promises, or other non-serializable items in my store state?](/docs/faq/OrganizingState.md#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state) - - [How do I organize nested or duplicate data in my state?](/docs/faq/OrganizingState.md#how-do-i-organize-nested-or-duplicate-data-in-my-state) + - [Do I have to put all my state into Redux? Should I ever use React's setState()?](faq/OrganizingState.md#do-i-have-to-put-all-my-state-into-redux-should-i-ever-use-reacts-setstate) + - [Can I put functions, promises, or other non-serializable items in my store state?](faq/OrganizingState.md#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state) + - [How do I organize nested or duplicate data in my state?](faq/OrganizingState.md#how-do-i-organize-nested-or-duplicate-data-in-my-state) + - [Should I put form state or other UI state in my store?](faq/OrganizingState.md#should-i-put-form-state-or-other-ui-state-in-my-store) - **Store Setup** - - [Can or should I create multiple stores? Can I import my store directly, and use it in components myself?](/docs/faq/StoreSetup.md#can-or-should-i-create-multiple-stores-can-i-import-my-store-directly-and-use-it-in-components-myself) - - [Is it OK to have more than one middleware chain in my store enhancer? What is the difference between next and dispatch in a middleware function?](/docs/faq/StoreSetup.md#is-it-ok-to-have-more-than-one-middleware-chain-in-my-store-enhancer-what-is-the-difference-between-next-and-dispatch-in-a-middleware-function) - - [How do I subscribe to only a portion of the state? Can I get the dispatched action as part of the subscription?](/docs/faq/StoreSetup.md#how-do-i-subscribe-to-only-a-portion-of-the-state-can-i-get-the-dispatched-action-as-part-of-the-subscription) + - [Can or should I create multiple stores? Can I import my store directly, and use it in components myself?](faq/StoreSetup.md#can-or-should-i-create-multiple-stores-can-i-import-my-store-directly-and-use-it-in-components-myself) + - [Is it OK to have more than one middleware chain in my store enhancer? What is the difference between next and dispatch in a middleware function?](faq/StoreSetup.md#is-it-ok-to-have-more-than-one-middleware-chain-in-my-store-enhancer-what-is-the-difference-between-next-and-dispatch-in-a-middleware-function) + - [How do I subscribe to only a portion of the state? Can I get the dispatched action as part of the subscription?](faq/StoreSetup.md#how-do-i-subscribe-to-only-a-portion-of-the-state-can-i-get-the-dispatched-action-as-part-of-the-subscription) - **Actions** - - [Why should type be a string, or at least serializable? Why should my action types be constants?](/docs/faq/Actions.md#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants) - - [Is there always a one-to-one mapping between reducers and actions?](/docs/faq/Actions.md#is-there-always-a-one-to-one-mapping-between-reducers-and-actions) - - [How can I represent “side effects” such as AJAX calls? Why do we need things like “action creators”, “thunks”, and “middleware” to do async behavior?](/docs/faq/Actions.md#how-can-i-represent-side-effects-such-as-ajax-calls-why-do-we-need-things-like-action-creators-thunks-and-middleware-to-do-async-behavior) - - [What async middleware should I use? How do you decide between thunks, sagas, observables, or something else?](/docs/faq/Actions.md#what-async-middleware-should-i-use-how-do-you-decide-between-thunks-sagas-observables-or-something-else) - - [Should I dispatch multiple actions in a row from one action creator?](/docs/faq/Actions.md#should-i-dispatch-multiple-actions-in-a-row-from-one-action-creator) + - [Why should type be a string, or at least serializable? Why should my action types be constants?](faq/Actions.md#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants) + - [Is there always a one-to-one mapping between reducers and actions?](faq/Actions.md#is-there-always-a-one-to-one-mapping-between-reducers-and-actions) + - [How can I represent “side effects” such as AJAX calls? Why do we need things like “action creators”, “thunks”, and “middleware” to do async behavior?](faq/Actions.md#how-can-i-represent-side-effects-such-as-ajax-calls-why-do-we-need-things-like-action-creators-thunks-and-middleware-to-do-async-behavior) + - [What async middleware should I use? How do you decide between thunks, sagas, observables, or something else?](faq/Actions.md#what-async-middleware-should-i-use-how-do-you-decide-between-thunks-sagas-observables-or-something-else) + - [Should I dispatch multiple actions in a row from one action creator?](faq/Actions.md#should-i-dispatch-multiple-actions-in-a-row-from-one-action-creator) - **Immutable Data** - - [What are the benefits of immutability?](/docs/faq/ImmutableData.md#what-are-the-benefits-of-immutability) - - [Why is immutability required by Redux?](/docs/faq/ImmutableData.md#why-is-immutability-required-by-redux) - - [What approaches are there for handling data immutability? Do I have to use Immutable.JS?](/docs/faq/ImmutableData.md#what-approaches-are-there-for-handling-data-immutability-do-i-have-to-use-immutable-js) - - [What are the issues with using JavaScript for immutable operations?](/docs/faq/ImmutableData.md#what-are-the-issues-with-using-plain-javascript-for-immutable-operations) + - [What are the benefits of immutability?](faq/ImmutableData.md#what-are-the-benefits-of-immutability) + - [Why is immutability required by Redux?](faq/ImmutableData.md#why-is-immutability-required-by-redux) + - [What approaches are there for handling data immutability? Do I have to use Immutable.JS?](faq/ImmutableData.md#what-approaches-are-there-for-handling-data-immutability-do-i-have-to-use-immutable-js) + - [What are the issues with using JavaScript for immutable operations?](faq/ImmutableData.md#what-are-the-issues-with-using-plain-javascript-for-immutable-operations) - **Using Immutable.JS with Redux** - - - [Why should I use an immutable-focused library such as Immutable.JS?](/docs/recipes/UsingImmutableJS.md#why-should-i-use-an-immutable-focused-library-such-as-immutable-js) - - [Why should I choose Immutable.JS as an immutable library?](/docs/recipes/UsingImmutableJS.md#why-should-i-choose-immutable-js-as-an-immutable-library) - - [What are the issues with using Immutable.JS?](/docs/recipes/UsingImmutableJS.md#what-are-the-issues-with-using-immutable-js) - - [Is Immutable.JS worth the effort?](/docs/recipes/UsingImmutableJS.md#is-using-immutable-js-worth-the-effort) - - [What are some opinionated Best Practices for using Immutable.JS with Redux?](/docs/recipes/UsingImmutableJS.md#what-are-some-opinionated-best-practices-for-using-immutable-js-with-redux) - + - [Why should I use an immutable-focused library such as Immutable.JS?](recipes/UsingImmutableJS.md#why-should-i-use-an-immutable-focused-library-such-as-immutable-js) + - [Why should I choose Immutable.JS as an immutable library?](recipes/UsingImmutableJS.md#why-should-i-choose-immutable-js-as-an-immutable-library) + - [What are the issues with using Immutable.JS?](recipes/UsingImmutableJS.md#what-are-the-issues-with-using-immutable-js) + - [Is Immutable.JS worth the effort?](recipes/UsingImmutableJS.md#is-using-immutable-js-worth-the-effort) + - [What are some opinionated Best Practices for using Immutable.JS with Redux?](recipes/UsingImmutableJS.md#what-are-some-opinionated-best-practices-for-using-immutable-js-with-redux) - **Code Structure** - - [What should my file structure look like? How should I group my action creators and reducers in my project? Where should my selectors go?](/docs/faq/CodeStructure.md#what-should-my-file-structure-look-like-how-should-i-group-my-action-creators-and-reducers-in-my-project-where-should-my-selectors-go) - - [How should I split my logic between reducers and action creators? Where should my “business logic” go?](/docs/faq/CodeStructure.md#how-should-i-split-my-logic-between-reducers-and-action-creators-where-should-my-business-logic-go) - - [Why should I use action creators?](/docs/faq/CodeStructure.md#why-should-i-use-action-creators) - - [Where should websockets and other persistent connections live?](/docs/faq/CodeStructure.md#where-should-websockets-and-other-persistent-connections-live) + - [What should my file structure look like? How should I group my action creators and reducers in my project? Where should my selectors go?](faq/CodeStructure.md#what-should-my-file-structure-look-like-how-should-i-group-my-action-creators-and-reducers-in-my-project-where-should-my-selectors-go) + - [How should I split my logic between reducers and action creators? Where should my “business logic” go?](faq/CodeStructure.md#how-should-i-split-my-logic-between-reducers-and-action-creators-where-should-my-business-logic-go) + - [Why should I use action creators?](faq/CodeStructure.md#why-should-i-use-action-creators) + - [Where should websockets and other persistent connections live?](faq/CodeStructure.md#where-should-websockets-and-other-persistent-connections-live) - **Performance** - - [How well does Redux “scale” in terms of performance and architecture?](/docs/faq/Performance.md#how-well-does-redux-scale-in-terms-of-performance-and-architecture) - - [Won't calling “all my reducers” for each action be slow?](/docs/faq/Performance.md#wont-calling-all-my-reducers-for-each-action-be-slow) - - [Do I have to deep-clone my state in a reducer? Isn't copying my state going to be slow?](/docs/faq/Performance.md#do-i-have-to-deep-clone-my-state-in-a-reducer-isnt-copying-my-state-going-to-be-slow) - - [How can I reduce the number of store update events?](/docs/faq/Performance.md#how-can-i-reduce-the-number-of-store-update-events) - - [Will having “one state tree” cause memory problems? Will dispatching many actions take up memory?](/docs/faq/Performance.md#will-having-one-state-tree-cause-memory-problems-will-dispatching-many-actions-take-up-memory) - - [Will caching remote data cause memory problems?](/docs/faq/Performance.md#will-caching-remote-data-cause-memory-problems) + - [How well does Redux “scale” in terms of performance and architecture?](faq/Performance.md#how-well-does-redux-scale-in-terms-of-performance-and-architecture) + - [Won't calling “all my reducers” for each action be slow?](faq/Performance.md#wont-calling-all-my-reducers-for-each-action-be-slow) + - [Do I have to deep-clone my state in a reducer? Isn't copying my state going to be slow?](faq/Performance.md#do-i-have-to-deep-clone-my-state-in-a-reducer-isnt-copying-my-state-going-to-be-slow) + - [How can I reduce the number of store update events?](faq/Performance.md#how-can-i-reduce-the-number-of-store-update-events) + - [Will having “one state tree” cause memory problems? Will dispatching many actions take up memory?](faq/Performance.md#will-having-one-state-tree-cause-memory-problems-will-dispatching-many-actions-take-up-memory) + - [Will caching remote data cause memory problems?](faq/Performance.md#will-caching-remote-data-cause-memory-problems) - **Design Decisions** - - [Why doesn't Redux pass the state and action to subscribers?](/docs/faq/DesignDecisions.md#why-doesnt-redux-pass-the-state-and-action-to-subscribers) - - [Why doesn't Redux support using classes for actions and reducers?](/docs/faq/DesignDecisions.md#why-doesnt-redux-support-using-classes-for-actions-and-reducers) - - [Why does the middleware signature use currying?](/docs/faq/DesignDecisions.md#why-does-the-middleware-signature-use-currying) - - [Why does applyMiddleware use a closure for dispatch?](/docs/faq/DesignDecisions.md#why-does-applymiddleware-use-a-closure-for-dispatch) - - [Why doesn't `combineReducers` include a third argument with the entire state when it calls each reducer?](/docs/faq/DesignDecisions.md#why-doesnt-combinereducers-include-a-third-argument-with-the-entire-state-when-it-calls-each-reducer) - - [Why doesn't mapDispatchToProps allow use of return values from `getState()` or `mapStateToProps()`?](/docs/faq/DesignDecisions.md#why-doesnt-mapdispatchtoprops-allow-use-of-return-values-from-getstate-or-mapstatetoprops) + - [Why doesn't Redux pass the state and action to subscribers?](faq/DesignDecisions.md#why-doesnt-redux-pass-the-state-and-action-to-subscribers) + - [Why doesn't Redux support using classes for actions and reducers?](faq/DesignDecisions.md#why-doesnt-redux-support-using-classes-for-actions-and-reducers) + - [Why does the middleware signature use currying?](faq/DesignDecisions.md#why-does-the-middleware-signature-use-currying) + - [Why does applyMiddleware use a closure for dispatch?](faq/DesignDecisions.md#why-does-applymiddleware-use-a-closure-for-dispatch) + - [Why doesn't `combineReducers` include a third argument with the entire state when it calls each reducer?](faq/DesignDecisions.md#why-doesnt-combinereducers-include-a-third-argument-with-the-entire-state-when-it-calls-each-reducer) + - [Why doesn't mapDispatchToProps allow use of return values from `getState()` or `mapStateToProps()`?](faq/DesignDecisions.md#why-doesnt-mapdispatchtoprops-allow-use-of-return-values-from-getstate-or-mapstatetoprops) - **React Redux** - - [Why isn't my component re-rendering, or my mapStateToProps running?](/docs/faq/ReactRedux.md#why-isnt-my-component-re-rendering-or-my-mapstatetoprops-running) - - [Why is my component re-rendering too often?](/docs/faq/ReactRedux.md#why-is-my-component-re-rendering-too-often) - - [How can I speed up my mapStateToProps?](/docs/faq/ReactRedux.md#how-can-i-speed-up-my-mapstatetoprops) - - [Why don't I have this.props.dispatch available in my connected component?](/docs/faq/ReactRedux.md#why-dont-i-have-this-props-dispatch-available-in-my-connected-component) - - [Should I only connect my top component, or can I connect multiple components in my tree?](/docs/faq/ReactRedux.md#should-i-only-connect-my-top-component-or-can-i-connect-multiple-components-in-my-tree) + - [Why should I use React-Redux?](faq/ReactRedux.md#why-should-i-use-react-redux) + - [Why isn't my component re-rendering, or my mapStateToProps running?](faq/ReactRedux.md#why-isnt-my-component-re-rendering-or-my-mapstatetoprops-running) + - [Why is my component re-rendering too often?](faq/ReactRedux.md#why-is-my-component-re-rendering-too-often) + - [How can I speed up my mapStateToProps?](faq/ReactRedux.md#how-can-i-speed-up-my-mapstatetoprops) + - [Why don't I have this.props.dispatch available in my connected component?](faq/ReactRedux.md#why-dont-i-have-this-props-dispatch-available-in-my-connected-component) + - [Should I only connect my top component, or can I connect multiple components in my tree?](faq/ReactRedux.md#should-i-only-connect-my-top-component-or-can-i-connect-multiple-components-in-my-tree) - **Miscellaneous** - - [Are there any larger, “real” Redux projects?](/docs/faq/Miscellaneous.md#are-there-any-larger-real-redux-projects) - - [How can I implement authentication in Redux?](/docs/faq/Miscellaneous.md#how-can-i-implement-authentication-in-redux) + - [Are there any larger, “real” Redux projects?](faq/Miscellaneous.md#are-there-any-larger-real-redux-projects) + - [How can I implement authentication in Redux?](faq/Miscellaneous.md#how-can-i-implement-authentication-in-redux) diff --git a/docs/Feedback.md b/docs/Feedback.md index 5e479bac02..2e632b8dd8 100644 --- a/docs/Feedback.md +++ b/docs/Feedback.md @@ -1,3 +1,10 @@ +--- +id: feedback +title: Feedback +sidebar_label: Feedback +hide_title: true +--- + # Feedback We appreciate feedback from the community. You can post feature requests and bug reports on [Product Pains](https://productpains.com/product/redux). diff --git a/docs/Glossary.md b/docs/Glossary.md index ba61ee1556..f1e2265239 100644 --- a/docs/Glossary.md +++ b/docs/Glossary.md @@ -1,3 +1,10 @@ +--- +id: glossary +title: Glossary +sidebar_label: Glossary +hide_title: true +--- + # Glossary This is a glossary of the core terms in Redux, along with their type signatures. The types are documented using [Flow notation](http://flowtype.org/docs/quick-reference.html). diff --git a/docs/README.md b/docs/README.md index 4ee1743c3b..2a48dcd0f6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -33,18 +33,18 @@ - [Computing Derived Data](recipes/ComputingDerivedData.md) - [Implementing Undo History](recipes/ImplementingUndoHistory.md) - [Isolating Subapps](recipes/IsolatingSubapps.md) - - [Structuring Reducers](recipes/StructuringReducers.md) - - [Prerequisite Concepts](recipes/reducers/PrerequisiteConcepts.md) - - [Basic Reducer Structure](recipes/reducers/BasicReducerStructure.md) - - [Splitting Reducer Logic](recipes/reducers/SplittingReducerLogic.md) - - [Refactoring Reducers Example](recipes/reducers/RefactoringReducersExample.md) - - [Using `combineReducers`](recipes/reducers/UsingCombineReducers.md) - - [Beyond `combineReducers`](recipes/reducers/BeyondCombineReducers.md) - - [Normalizing State Shape](recipes/reducers/NormalizingStateShape.md) - - [Updating Normalized Data](recipes/reducers/UpdatingNormalizedData.md) - - [Reusing Reducer Logic](recipes/reducers/ReusingReducerLogic.md) - - [Immutable Update Patterns](recipes/reducers/ImmutableUpdatePatterns.md) - - [Initializing State](recipes/reducers/InitializingState.md) + - [Structuring Reducers](recipes/structuring-reducers/StructuringReducers.md) + - [Prerequisite Concepts](recipes/structuring-reducers/PrerequisiteConcepts.md) + - [Basic Reducer Structure](recipes/structuring-reducers/BasicReducerStructure.md) + - [Splitting Reducer Logic](recipes/structuring-reducers/SplittingReducerLogic.md) + - [Refactoring Reducers Example](recipes/structuring-reducers/RefactoringReducersExample.md) + - [Using `combineReducers`](recipes/structuring-reducers/UsingCombineReducers.md) + - [Beyond `combineReducers`](recipes/structuring-reducers/BeyondCombineReducers.md) + - [Normalizing State Shape](recipes/structuring-reducers/NormalizingStateShape.md) + - [Updating Normalized Data](recipes/structuring-reducers/UpdatingNormalizedData.md) + - [Reusing Reducer Logic](recipes/structuring-reducers/ReusingReducerLogic.md) + - [Immutable Update Patterns](recipes/structuring-reducers/ImmutableUpdatePatterns.md) + - [Initializing State](recipes/structuring-reducers/InitializingState.md) - [Using Immutable.JS with Redux](recipes/UsingImmutableJS.md) - [FAQ](FAQ.md) - [General](faq/General.md) diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md index 2ad16f3699..27d89aaee8 100644 --- a/docs/Troubleshooting.md +++ b/docs/Troubleshooting.md @@ -1,3 +1,10 @@ +--- +id: troubleshooting +title: Troubleshooting +sidebar_label: Troubleshooting +hide_title: true +--- + # Troubleshooting This is a place to share common problems and solutions to them. @@ -119,7 +126,7 @@ return state.map((todo, index) => { Note that experimental language features are subject to change. -Also keep an eye out for nested state objects that need to be deeply copied. Both `_.extend` and `Object.assign` make a shallow copy of the state. See [Updating Nested Objects](/docs/recipes/reducers/ImmutableUpdatePatterns.md#updating-nested-objects) for suggestions on how to deal with nested state objects. +Also keep an eye out for nested state objects that need to be deeply copied. Both `_.extend` and `Object.assign` make a shallow copy of the state. See [Updating Nested Objects](./recipes/structuring-reducers/ImmutableUpdatePatterns.md#updating-nested-objects) for suggestions on how to deal with nested state objects. #### Don't forget to call [`dispatch(action)`](api/Store.md#dispatch) diff --git a/docs/advanced/AsyncActions.md b/docs/advanced/AsyncActions.md index 6a16e8535b..6933b492ea 100644 --- a/docs/advanced/AsyncActions.md +++ b/docs/advanced/AsyncActions.md @@ -1,3 +1,10 @@ +--- +id: async-actions +title: Async Actions +sidebar_label: Async Actions +hide_title: true +--- + # Async Actions In the [basics guide](../basics/README.md), we built a simple todo application. It was fully synchronous. Every time an action was dispatched, the state was updated immediately. @@ -38,7 +45,7 @@ Or you can define separate types for them: { type: 'FETCH_POSTS_SUCCESS', response: { ... } } ``` -Choosing whether to use a single action type with flags, or multiple action types, is up to you. It's a convention you need to decide with your team. Multiple types leave less room for a mistake, but this is not an issue if you generate action creators and reducers with a helper library like [redux-actions](https://github.com/acdlite/redux-actions). +Choosing whether to use a single action type with flags, or multiple action types, is up to you. It's a convention you need to decide with your team. Multiple types leave less room for a mistake, but this is not an issue if you generate action creators and reducers with a helper library like [redux-actions](https://redux-actions.js.org/). Whatever convention you choose, stick with it throughout the application. We'll use separate types in this tutorial. diff --git a/docs/advanced/AsyncFlow.md b/docs/advanced/AsyncFlow.md index 1d8d74c3b8..af061b4ccf 100644 --- a/docs/advanced/AsyncFlow.md +++ b/docs/advanced/AsyncFlow.md @@ -1,3 +1,10 @@ +--- +id: async-flow +title: Async Flow +sidebar_label: Async Flow +hide_title: true +--- + # Async Flow Without [middleware](Middleware.md), Redux store only supports [synchronous data flow](../basics/DataFlow.md). This is what you get by default with [`createStore()`](../api/createStore.md). diff --git a/docs/advanced/ExampleRedditAPI.md b/docs/advanced/ExampleRedditAPI.md index cde5aec53f..49102d986d 100644 --- a/docs/advanced/ExampleRedditAPI.md +++ b/docs/advanced/ExampleRedditAPI.md @@ -1,3 +1,10 @@ +--- +id: example-reddit-api +title: Example: Reddit API +sidebar_label: Example: Reddit API +hide_title: true +--- + # Example: Reddit API This is the complete source code of the Reddit headline fetching example we built during the [advanced tutorial](README.md). diff --git a/docs/advanced/Middleware.md b/docs/advanced/Middleware.md index 4374c5f323..f249bcad27 100644 --- a/docs/advanced/Middleware.md +++ b/docs/advanced/Middleware.md @@ -1,3 +1,10 @@ +--- +id: middleware +title: Middleware +sidebar_label: Middleware +hide_title: true +--- + # Middleware You've seen middleware in action in the [Async Actions](../advanced/AsyncActions.md) example. If you've used server-side libraries like [Express](http://expressjs.com/) and [Koa](http://koajs.com/), you were also probably already familiar with the concept of _middleware_. In these frameworks, middleware is some code you can put between the framework receiving a request, and the framework generating a response. For example, Express or Koa middleware may add CORS headers, logging, compression, and more. The best feature of middleware is that it's composable in a chain. You can use multiple independent third-party middleware in a single project. @@ -16,7 +23,7 @@ One of the benefits of Redux is that it makes state changes predictable and tran Wouldn't it be nice if we logged every action that happens in the app, together with the state computed after it? When something goes wrong, we can look back at our log, and figure out which action corrupted the state. - + How do we approach this with Redux? diff --git a/docs/advanced/NextSteps.md b/docs/advanced/NextSteps.md index f09353649d..52737bf2e5 100644 --- a/docs/advanced/NextSteps.md +++ b/docs/advanced/NextSteps.md @@ -1,3 +1,10 @@ +--- +id: next-steps +title: Next Steps +sidebar_label: Next Steps +hide_title: true +--- + # Next Steps If you landed in this section, you might be wondering at this point, "what should I do now?". Here is where we provide some essential tips/suggestions on how to diverge from creating trivial TodoMVC apps to a real world application. diff --git a/docs/advanced/README.md b/docs/advanced/README.md index f879b29045..122e1d930d 100644 --- a/docs/advanced/README.md +++ b/docs/advanced/README.md @@ -1,3 +1,10 @@ +--- +id: advanced-tutorial +title: Advanced Tutorial: Intro +sidebar_label: Advanced Tutorial: Intro +hide_title: true +--- + # Advanced In the [basics walkthrough](../basics/README.md), we explored how to structure a simple Redux application. In this walkthrough, we will explore how AJAX and routing fit into the picture. diff --git a/docs/advanced/UsageWithReactRouter.md b/docs/advanced/UsageWithReactRouter.md index 41a7cdcba8..02661d9ef7 100644 --- a/docs/advanced/UsageWithReactRouter.md +++ b/docs/advanced/UsageWithReactRouter.md @@ -1,3 +1,10 @@ +--- +id: usage-with-react-router +title: Usage with React Router +sidebar_label: Usage with React Router +hide_title: true +--- + # Usage with React Router So you want to do routing with your Redux app. You can use it with [React Router](https://github.com/ReactTraining/react-router). Redux will be the source of truth for your data and React Router will be the source of truth for your URL. In most of the cases, **it is fine** to have them separate unless you need to time travel and rewind actions that trigger a URL change. @@ -65,7 +72,7 @@ We will then import the `` from React Redux: import { Provider } from 'react-redux' ``` -We will wrap `` in `` so that route handlers can get [access to the `store`](http://redux.js.org/docs/basics/UsageWithReact.html#passing-the-store). +We will wrap `` in `` so that route handlers can get [access to the `store`](../basics/UsageWithReact.md#passing-the-store). ```js const Root = ({ store }) => ( @@ -125,7 +132,7 @@ render(, document.getElementById('root')) ## Navigating with React Router -React Router comes with a [``](https://github.com/ReactTraining/react-router/blob/v3/docs/API.md#link) component that lets you navigate around your application. If you want to add some styles, `react-router-dom` has another special `` called [``](https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/NavLink.md), which accepts styling props. For instance, the `activeStyle` property lets us apply a style on the active state. +React Router comes with a [``](https://reacttraining.com/react-router/web/api/Link) component that lets you navigate around your application. If you want to add some styles, `react-router-dom` has another special `` called [``](https://reacttraining.com/react-router/web/api/NavLink), which accepts styling props. For instance, the `activeStyle` property lets us apply a style on the active state. In our example, we can wrap `` with a new container component `` so as to dynamically change the URL. diff --git a/docs/api/README.md b/docs/api/README.md index a7981f4d67..40639ac2e2 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -1,3 +1,10 @@ +--- +id: api-reference +title: API Reference +sidebar_label: API Reference +hide_title: true +--- + # API Reference The Redux API surface is tiny. Redux defines a set of contracts for you to implement (such as [reducers](../Glossary.md#reducer)) and provides a few helper functions to tie these contracts together. diff --git a/docs/api/Store.md b/docs/api/Store.md index d03d27ca85..1bddfe5617 100644 --- a/docs/api/Store.md +++ b/docs/api/Store.md @@ -1,3 +1,10 @@ +--- +id: store +title: Store +sidebar_label: Store +hide_title: true +--- + # Store A store holds the whole [state tree](../Glossary.md#state) of your application. @@ -15,7 +22,7 @@ To create it, pass your root [reducing function](../Glossary.md#reducer) to [`cr - [`getState()`](#getState) - [`dispatch(action)`](#dispatch) - [`subscribe(listener)`](#subscribe) -- [`replaceReducer(nextReducer)`](#replacereducer) +- [`replaceReducer(nextReducer)`](#replaceReducer) ## Store Methods diff --git a/docs/api/applyMiddleware.md b/docs/api/applyMiddleware.md index 1d898954a0..63f310bdeb 100644 --- a/docs/api/applyMiddleware.md +++ b/docs/api/applyMiddleware.md @@ -1,3 +1,10 @@ +--- +id: applymiddleware +title: applyMiddleware +sidebar_label: applyMiddleware +hide_title: true +--- + # `applyMiddleware(...middleware)` Middleware is the suggested way to extend Redux with custom functionality. Middleware lets you wrap the store's [`dispatch`](Store.md#dispatch) method for fun and profit. The key feature of middleware is that it is composable. Multiple middleware can be combined together, where each middleware requires no knowledge of what comes before or after it in the chain. @@ -14,7 +21,7 @@ Middleware is not baked into [`createStore`](createStore.md) and is not a fundam #### Returns -(_Function_) A store enhancer that applies the given middleware. The store enhancer signature is `createStore => createStore'` but the easiest way to apply it is to pass it to [`createStore()`](./createStore.md) as the last `enhancer` argument. +(_Function_) A store enhancer that applies the given middleware. The store enhancer signature is `createStore => createStore` but the easiest way to apply it is to pass it to [`createStore()`](./createStore.md) as the last `enhancer` argument. #### Example: Custom Logger Middleware @@ -172,9 +179,9 @@ class SandwichShop extends Component { this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson)) } - componentWillReceiveProps(nextProps) { - if (nextProps.forPerson !== this.props.forPerson) { - this.props.dispatch(makeASandwichWithSecretSauce(nextProps.forPerson)) + componentDidUpdate(prevProps) { + if (prevProps.forPerson !== this.props.forPerson) { + this.props.dispatch(makeASandwichWithSecretSauce(this.props.forPerson)) } } diff --git a/docs/api/bindActionCreators.md b/docs/api/bindActionCreators.md index e81a070284..94af4448b7 100644 --- a/docs/api/bindActionCreators.md +++ b/docs/api/bindActionCreators.md @@ -1,3 +1,10 @@ +--- +id: bindactioncreators +title: bindActionCreators +sidebar_label: bindActionCreators +hide_title: true +--- + # `bindActionCreators(actionCreators, dispatch)` Turns an object whose values are [action creators](../Glossary.md#action-creator), into an object with the same keys, but with every action creator wrapped into a [`dispatch`](Store.md#dispatch) call so they may be invoked directly. @@ -6,7 +13,7 @@ Normally you should just call [`dispatch`](Store.md#dispatch) directly on your [ The only use case for `bindActionCreators` is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass [`dispatch`](Store.md#dispatch) or the Redux store to it. -For convenience, you can also pass a single function as the first argument, and get a function in return. +For convenience, you can also pass an action creator as the first argument, and get a dispatch wrapped function in return. #### Parameters @@ -107,4 +114,4 @@ export default connect(state => ({ todos: state.todos }))(TodoListContainer) - You might ask: why don't we bind the action creators to the store instance right away, like in classical Flux? The problem is that this won't work well with universal apps that need to render on the server. Most likely you want to have a separate store instance per request so you can prepare them with different data, but binding action creators during their definition means you're stuck with a single store instance for all requests. -- If you use ES5, instead of `import * as` syntax you can just pass `require('./TodoActionCreators')` to `bindActionCreators` as the first argument. The only thing it cares about is that the values of the `actionCreators` arguments are functions. The module system doesn't matter. +- If you use ES5, instead of `import * as` syntax you can just pass `require('./TodoActionCreators')` to `bindActionCreators` as the first argument. The only thing it cares about is that the values of the `actionCreators` properties are functions. The module system doesn't matter. diff --git a/docs/api/combineReducers.md b/docs/api/combineReducers.md index 6be8b86fdf..09af2c693f 100644 --- a/docs/api/combineReducers.md +++ b/docs/api/combineReducers.md @@ -1,3 +1,10 @@ +--- +id: combinereducers +title: combineReducers +sidebar_label: combineReducers +hide_title: true +--- + # `combineReducers(reducers)` As your app grows more complex, you'll want to split your [reducing function](../Glossary.md#reducer) into separate functions, each managing independent parts of the [state](../Glossary.md#state). @@ -9,7 +16,7 @@ The resulting reducer calls every child reducer, and gathers their results into Example: -``` +```js rootReducer = combineReducers({potato: potatoReducer, tomato: tomatoReducer}) // This would produce the following state object { diff --git a/docs/api/compose.md b/docs/api/compose.md index 3c419cc69c..bb9b65f8ad 100644 --- a/docs/api/compose.md +++ b/docs/api/compose.md @@ -1,3 +1,10 @@ +--- +id: compose +title: compose +sidebar_label: compose +hide_title: true +--- + # `compose(...functions)` Composes functions from right to left. diff --git a/docs/api/createStore.md b/docs/api/createStore.md index 20af6c7094..772734472b 100644 --- a/docs/api/createStore.md +++ b/docs/api/createStore.md @@ -1,3 +1,10 @@ +--- +id: createstore +title: createStore +sidebar_label: createStore +hide_title: true +--- + # `createStore(reducer, [preloadedState], [enhancer])` Creates a Redux [store](Store.md) that holds the complete state tree of your app. diff --git a/docs/basics/Actions.md b/docs/basics/Actions.md index 256e1cc273..8b32884d04 100644 --- a/docs/basics/Actions.md +++ b/docs/basics/Actions.md @@ -1,3 +1,10 @@ +--- +id: actions +title: Actions +sidebar_label: Actions +hide_title: true +--- + # Actions First, let's define some actions. @@ -95,7 +102,7 @@ const boundCompleteTodo = index => dispatch(completeTodo(index)) Now you'll be able to call them directly: -``` +```js boundAddTodo(text) boundCompleteTodo(index) ``` diff --git a/docs/basics/DataFlow.md b/docs/basics/DataFlow.md index 0f0abd2ea7..a1015f9dee 100644 --- a/docs/basics/DataFlow.md +++ b/docs/basics/DataFlow.md @@ -1,3 +1,10 @@ +--- +id: data-flow +title: Data flow +sidebar_label: Data flow +hide_title: true +--- + # Data Flow Redux architecture revolves around a **strict unidirectional data flow**. diff --git a/docs/basics/ExampleTodoList.md b/docs/basics/ExampleTodoList.md index 56d26ba598..a0b5bf2788 100644 --- a/docs/basics/ExampleTodoList.md +++ b/docs/basics/ExampleTodoList.md @@ -1,3 +1,10 @@ +--- +id: example +title: Example: Todo List +sidebar_label: Example: Todo List +hide_title: true +--- + # Example: Todo List This is the complete source code of the tiny todo app we built during the [basics tutorial](./README.md). This code is also in [our repository of examples](https://github.com/reduxjs/redux/tree/master/examples/todos/src) and can be [run in your browser via CodeSandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos). diff --git a/docs/basics/README.md b/docs/basics/README.md index f07ffc7f2d..d4f211f767 100644 --- a/docs/basics/README.md +++ b/docs/basics/README.md @@ -1,3 +1,10 @@ +--- +id: basic-tutorial +title: Basic Tutorial: Intro +sidebar_label: Basic Tutorial: Intro +hide_title: true +--- + # Basics Don't be fooled by all the fancy talk about reducers, middleware, store enhancers—Redux is incredibly simple. If you've ever built a Flux application, you will feel right at home. If you're new to Flux, it's easy too! diff --git a/docs/basics/Reducers.md b/docs/basics/Reducers.md index d0e42db694..53cb3f016b 100644 --- a/docs/basics/Reducers.md +++ b/docs/basics/Reducers.md @@ -1,3 +1,10 @@ +--- +id: reducers +title: Reducers +sidebar_label: Reducers +hide_title: true +--- + # Reducers **Reducers** specify how the application's state changes in response to [actions](./Actions.md) sent to the store. Remember that actions only describe _what happened_, but don't describe how the application's state changes. @@ -37,8 +44,8 @@ You'll often find that you need to store some data, as well as some UI state, in Now that we've decided what our state object looks like, we're ready to write a reducer for it. The reducer is a pure function that takes the previous state and an action, and returns the next state. -```js -;(previousState, action) => newState +``` +(previousState, action) => newState ``` It's called a reducer because it's the type of function you would pass to [`Array.prototype.reduce(reducer, ?initialValue)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce). It's very important that the reducer stays pure. Things you should **never** do inside a reducer: @@ -254,7 +261,7 @@ function todoApp(state = initialState, action) { } ``` -Note that `todos` also accepts `state`—but it's an array! Now `todoApp` just gives it the slice of the state to manage, and `todos` knows how to update just that slice. **This is called _reducer composition_, and it's the fundamental pattern of building Redux apps.** +Note that `todos` also accepts `state`—but `state` is an array! Now `todoApp` gives `todos` just a slice of the state to manage, and `todos` knows how to update just that slice. **This is called _reducer composition_, and it's the fundamental pattern of building Redux apps.** Let's explore reducer composition more. Can we also extract a reducer managing just `visibilityFilter`? We can. diff --git a/docs/basics/Store.md b/docs/basics/Store.md index bc3b0f705f..28233de626 100644 --- a/docs/basics/Store.md +++ b/docs/basics/Store.md @@ -1,3 +1,10 @@ +--- +id: store +title: Store +sidebar_label: Store +hide_title: true +--- + # Store In the previous sections, we defined the [actions](Actions.md) that represent the facts about “what happened” and the [reducers](Reducers.md) that update the state according to those actions. @@ -59,7 +66,7 @@ unsubscribe() You can see how this causes the state held by the store to change: - + We specified the behavior of our app before we even started writing the UI. We won't do this in this tutorial, but at this point you can write tests for your reducers and action creators. You won't need to mock anything because they are just [pure](../introduction/ThreePrinciples.md#changes-are-made-with-pure-functions) functions. Call them, and make assertions on what they return. diff --git a/docs/basics/UsageWithReact.md b/docs/basics/UsageWithReact.md index d02e113653..1450be4a58 100644 --- a/docs/basics/UsageWithReact.md +++ b/docs/basics/UsageWithReact.md @@ -1,16 +1,25 @@ +--- +id: usage-with-react +title: Usage with React +sidebar_label: Usage with React +hide_title: true +--- + # Usage with React From the very beginning, we need to stress that Redux has no relation to React. You can write Redux apps with React, Angular, Ember, jQuery, or vanilla JavaScript. That said, Redux works especially well with libraries like [React](http://facebook.github.io/react/) and [Deku](https://github.com/dekujs/deku) because they let you describe UI as a function of state, and Redux emits state updates in response to actions. -We will use React to build our simple todo app. +We will use React to build our simple todo app, and cover the basics of how to use React with Redux. + +> **Note**: see **the official React-Redux docs at https://react-redux.js.org** for a complete guide on how to use Redux and React together. ## Installing React Redux [React bindings](https://github.com/reduxjs/react-redux) are not included in Redux by default. You need to install them explicitly: -``` +```sh npm install --save react-redux ``` @@ -59,7 +68,7 @@ React bindings for Redux separate _presentational_ components from _container_ c Most of the components we'll write will be presentational, but we'll need to generate a few container components to connect them to the Redux store. This and the design brief below do not imply container components must be near the top of the component tree. If a container component becomes too complex (i.e. it has heavily nested presentational components with countless callbacks being passed down), introduce another container within the component tree as noted in the [FAQ](../faq/ReactRedux.md#react-multiple-components). -Technically you could write the container components by hand using [`store.subscribe()`](../api/Store.md#subscribe). We don't advise you to do this because React Redux makes many performance optimizations that are hard to do by hand. For this reason, rather than write container components, we will generate them using the [`connect()`](https://github.com/reduxjs/react-redux/blob/master/docs/api.md#connect) function provided by React Redux, as you will see below. +Technically you could write the container components by hand using [`store.subscribe()`](../api/Store.md#subscribe). We don't advise you to do this because React Redux makes many performance optimizations that are hard to do by hand. For this reason, rather than write container components, we will generate them using the [`connect()`](https://react-redux.js.org/api#connect) function provided by React Redux, as you will see below. ## Designing Component Hierarchy @@ -219,7 +228,7 @@ export default Footer ### Implementing Container Components -Now it's time to hook up those presentational components to Redux by creating some containers. Technically, a container component is just a React component that uses [`store.subscribe()`](../api/Store.md#subscribe) to read a part of the Redux state tree and supply props to a presentational component it renders. You could write a container component by hand, but we suggest instead generating container components with the React Redux library's [`connect()`](https://github.com/reduxjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) function, which provides many useful optimizations to prevent unnecessary re-renders. (One result of this is that you shouldn't have to worry about the [React performance suggestion](https://facebook.github.io/react/docs/advanced-performance.html) of implementing `shouldComponentUpdate` yourself.) +Now it's time to hook up those presentational components to Redux by creating some containers. Technically, a container component is just a React component that uses [`store.subscribe()`](../api/Store.md#subscribe) to read a part of the Redux state tree and supply props to a presentational component it renders. You could write a container component by hand, but we suggest instead generating container components with the React Redux library's [`connect()`](https://react-redux.js.org/using-react-redux/connect-mapstate) function, which provides many useful optimizations to prevent unnecessary re-renders. (One result of this is that you shouldn't have to worry about the [React performance suggestion](https://facebook.github.io/react/docs/advanced-performance.html) of implementing `shouldComponentUpdate` yourself.) To use `connect()`, you need to define a special function called `mapStateToProps` that describes how to transform the current Redux store state into the props you want to pass to a presentational component you are wrapping. For example, `VisibleTodoList` needs to calculate `todos` to pass to the `TodoList`, so we define a function that filters the `state.todos` according to the `state.visibilityFilter`, and use it in its `mapStateToProps`: @@ -409,7 +418,7 @@ export default App All container components need access to the Redux store so they can subscribe to it. One option would be to pass it as a prop to every container component. However it gets tedious, as you have to wire `store` even through presentational components just because they happen to render a container deep in the component tree. -The option we recommend is to use a special React Redux component called [``](https://github.com/reduxjs/react-redux/blob/master/docs/api.md#provider-store) to [magically](https://facebook.github.io/react/docs/context.html) make the store available to all container components in the application without passing it explicitly. You only need to use it once when you render the root component: +The option we recommend is to use a special React Redux component called [``](https://react-redux.js.org/api/provider) to [magically](https://facebook.github.io/react/docs/context.html) make the store available to all container components in the application without passing it explicitly. You only need to use it once when you render the root component: #### `index.js` @@ -433,4 +442,8 @@ render( ## Next Steps -Read the [complete source code for this tutorial](ExampleTodoList.md) to better internalize the knowledge you have gained. Then, head straight to the [advanced tutorial](../advanced/README.md) to learn how to handle network requests and routing! +Read the [complete source code for this tutorial](ExampleTodoList.md) to better internalize the knowledge you have gained. +Then, head straight to the [advanced tutorial](../advanced/README.md) to learn how to handle network requests and routing! + +You should also take some time to **[read through the React-Redux docs](https://react-redux.js.org)** to get +a better understanding of how to use React and Redux together. diff --git a/docs/faq/Actions.md b/docs/faq/Actions.md index 2540ca17dc..d961a6e60b 100644 --- a/docs/faq/Actions.md +++ b/docs/faq/Actions.md @@ -1,3 +1,10 @@ +--- +id: actions +title: Actions +sidebar_label: Actions +hide_title: true +--- + # Redux FAQ: Actions ## Table of Contents @@ -22,7 +29,7 @@ Encapsulating and centralizing commonly used pieces of code is a key concept in **Documentation** -- [Reducing Boilerplate](/docs/recipes/ReducingBoilerplate.md#actions) +- [Reducing Boilerplate](../recipes/ReducingBoilerplate.md#actions) **Discussion** @@ -41,8 +48,8 @@ No. We suggest you write independent small reducer functions that are each respo **Documentation** -- [Basics: Reducers](/docs/basics/Reducers.md) -- [Recipes: Structuring Reducers](/docs/recipes/StructuringReducers.md) +- [Basics: Reducers](../basics/Reducers.md) +- [Recipes: Structuring Reducers](../recipes/structuring-reducers/StructuringReducers.md) **Discussions** @@ -67,9 +74,9 @@ The simplest and most common way to do this is to add the [Redux Thunk](https:// **Documentation** -- [Advanced: Async Actions](/docs/advanced/AsyncActions.md) -- [Advanced: Async Flow](/docs/advanced/AsyncFlow.md) -- [Advanced: Middleware](/docs/advanced/Middleware.md) +- [Advanced: Async Actions](../advanced/AsyncActions.md) +- [Advanced: Async Flow](../advanced/AsyncFlow.md) +- [Advanced: Middleware](../advanced/Middleware.md) **Articles** @@ -134,7 +141,7 @@ Try to avoid dispatching several times synchronously in a row in the places wher **Documentation** -- [FAQ: Performance - Reducing Update Events](/docs/faq/Performance.md#performance-update-events) +- [FAQ: Performance - Reducing Update Events](./Performance.md#performance-update-events) **Articles** diff --git a/docs/faq/CodeStructure.md b/docs/faq/CodeStructure.md index cfc0e0b699..db3a82aa6e 100644 --- a/docs/faq/CodeStructure.md +++ b/docs/faq/CodeStructure.md @@ -1,3 +1,10 @@ +--- +id: code-structure +title: Code Structure +sidebar_label: Code Structure +hide_title: true +--- + # Redux FAQ: Code Structure ## Table of Contents @@ -25,7 +32,7 @@ While it ultimately doesn't matter how you lay out your code on disk, it's impor **Documentation** -- [FAQ: Actions - "1:1 mapping between reducers and actions?"](/docs/faq/Actions.md#actions-reducer-mappings) +- [FAQ: Actions - "1:1 mapping between reducers and actions?"](./Actions.md#actions-reducer-mappings) **Articles** diff --git a/docs/faq/DesignDecisions.md b/docs/faq/DesignDecisions.md index 23ae56e2d6..f2ca266651 100644 --- a/docs/faq/DesignDecisions.md +++ b/docs/faq/DesignDecisions.md @@ -1,3 +1,10 @@ +--- +id: design-decisions +title: Design Decisions +sidebar_label: Design Decisions +hide_title: true +--- + # Redux FAQ: Design Decisions ## Table of Contents @@ -13,7 +20,7 @@ ### Why doesn't Redux pass the state and action to subscribers? -Subscribers are intended to respond to the state value itself, not the action. Updates to the state are processed synchronously, but notifications to subscribers can be batched or debounced, meaning that subscribers are not always notified with every action. This is a common [performance optimization](http://redux.js.org/docs/faq/Performance.html#performance-update-events) to avoid repeated re-rendering. +Subscribers are intended to respond to the state value itself, not the action. Updates to the state are processed synchronously, but notifications to subscribers can be batched or debounced, meaning that subscribers are not always notified with every action. This is a common [performance optimization](./Performance.md#performance-update-events) to avoid repeated re-rendering. Batching or debouncing is possible by using enhancers to override `store.dispatch` to change the way that subscribers are notified. Also, there are libraries that change Redux to process actions in batches to optimize performance and avoid repeated re-rendering: @@ -27,7 +34,7 @@ A potential use-case for using the action inside a subscriber -- which is an uns 1. the [shouldComponentUpdate](https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate) lifecycle method 2. the [virtual DOM equality check (vDOMEq)](https://facebook.github.io/react/docs/optimizing-performance.html#avoid-reconciliation) 3. [React.PureComponent](https://facebook.github.io/react/docs/optimizing-performance.html#examples) -4. Using React-Redux: use [mapStateToProps](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) to subscribe components to only the parts of the store that they need. +4. Using React-Redux: use [mapStateToProps](https://react-redux.js.org/api#connect) to subscribe components to only the parts of the store that they need. #### Further Information @@ -87,7 +94,7 @@ The [curried function signature](https://github.com/reactjs/redux/issues/1744) o ### Why doesn't `combineReducers` include a third argument with the entire state when it calls each reducer? -`combineReducers` is opinionated to encourage splitting reducer logic by domain. As stated in [Beyond `combineReducers`](../recipes/reducers/BeyondCombineReducers.md),`combineReducers` is deliberately limited to handle a single common use case: updating a state tree that is a plain Javascript object by delegating the work of updating each slice of state to a specific slice reducer. +`combineReducers` is opinionated to encourage splitting reducer logic by domain. As stated in [Beyond `combineReducers`](../recipes/structuring-reducers/BeyondCombineReducers.md),`combineReducers` is deliberately limited to handle a single common use case: updating a state tree that is a plain Javascript object by delegating the work of updating each slice of state to a specific slice reducer. It's not immediately obvious what a potential third argument to each reducer should be: the entire state tree, some callback function, some other part of the state tree, etc. If `combineReducers` doesn't fit your use case, consider using libraries like [combineSectionReducers](https://github.com/ryo33/combine-section-reducers) or [reduceReducers](https://github.com/acdlite/reduce-reducers) for other options with deeply nested reducers and reducers that require access to the global state. @@ -97,7 +104,7 @@ If none of the published utilities solve your use case, you can always write a f **Articles** -- [Beyond `combineReducers`](../recipes/reducers/BeyondCombineReducers.md) +- [Beyond `combineReducers`](../recipes/structuring-reducers/BeyondCombineReducers.md) **Discussions** diff --git a/docs/faq/General.md b/docs/faq/General.md index d18bda0ba6..8a8bf2b4c4 100644 --- a/docs/faq/General.md +++ b/docs/faq/General.md @@ -1,3 +1,10 @@ +--- +id: general +title: General +sidebar_label: General +hide_title: true +--- + # Redux FAQ: General ## Table of Contents @@ -53,7 +60,7 @@ In the end, Redux is just a tool. It's a great tool, and there are some great re **Documentation** -- [Introduction: Motivation](/docs/introduction/Motivation.md) +- [Introduction: Motivation](../introduction/Motivation.md) **Articles** diff --git a/docs/faq/ImmutableData.md b/docs/faq/ImmutableData.md index 2f26c027d5..18878fbcf2 100644 --- a/docs/faq/ImmutableData.md +++ b/docs/faq/ImmutableData.md @@ -1,12 +1,29 @@ +--- +id: immutable-data +title: Immutable Data +sidebar_label: Immutable Data +hide_title: true +--- + # Redux FAQ: Immutable Data ## Table of Contents - [What are the benefits of immutability?](#what-are-the-benefits-of-immutability) - [Why is immutability required by Redux?](#why-is-immutability-required-by-redux) -- [Why does Redux’s use of shallow equality checking require immutability?](#why-does-reduxs-use-of-shallow-equality-checking-require-immutability) - [How do Shallow and Deep Equality Checking differ?](#how-do-shallow-and-deep-equality-checking-differ) - [How does Redux use shallow equality checking?](#how-does-redux-use-shallow-equality-checking) - [How does `combineReducers` use shallow equality checking?](#how-does-combinereducers-use-shallow-equality-checking) - [How does React-Redux use shallow equality checking?](#how-does-react-redux-use-shallow-equality-checking) - [How does React-Redux use shallow equality checking to determine whether a component needs re-rendering?](#how-does-react-redux-use-shallow-equality-checking-to-determine-whether-a-component-needs-re-rendering) - [Why will shallow equality checking not work with mutable objects?](#why-will-shallow-equality-checking-not-work-with-mutable-objects) - [Does shallow equality checking with a mutable object cause problems with Redux?](#does-shallow-equality-checking-with-a-mutable-object-cause-problems-with-redux) - [Why does a reducer mutating the state prevent React-Redux from re-rendering a wrapped component?](#why-does-a-reducer-mutating-the-state-prevent-react-redux-from-re-rendering-a-wrapped-component) - [Why does a selector mutating and returning a persistent object to `mapStateToProps` prevent React-Redux from re-rendering a wrapped component?](#why-does-a-selector-mutating-and-returning-a-persistent-object-to-mapstatetoprops-prevent-react-redux-from-re-rendering-a-wrapped-component) - [How does immutability enable a shallow check to detect object mutations?](#how-does-immutability-enable-a-shallow-check-to-detect-object-mutations) -- [How can immutability in your reducers cause components to render unnecessarily?](#how-can-immutability-in-your-reducers-cause-components-to-render-unnecessarily) -- [How can immutability in mapStateToProps cause components to render unnecessarily?](#how-can-immutability-in-mapstatetoprops-cause-components-to-render-unnecessarily) +- [Why does Redux’s use of shallow equality checking require immutability?](#why-does-reduxs-use-of-shallow-equality-checking-require-immutability) + - [How do Shallow and Deep Equality Checking differ?](#how-do-shallow-and-deep-equality-checking-differ) + - [How does Redux use shallow equality checking?](#how-does-redux-use-shallow-equality-checking) + - [How does `combineReducers` use shallow equality checking?](#how-does-combinereducers-use-shallow-equality-checking) + - [How does React-Redux use shallow equality checking?](#how-does-react-redux-use-shallow-equality-checking) + - [How does React-Redux use shallow equality checking to determine whether a component needs re-rendering?](#how-does-react-redux-use-shallow-equality-checking-to-determine-whether-a-component-needs-re-rendering) + - [Why will shallow equality checking not work with mutable objects?](#why-will-shallow-equality-checking-not-work-with-mutable-objects) + - [Does shallow equality checking with a mutable object cause problems with Redux?](#does-shallow-equality-checking-with-a-mutable-object-cause-problems-with-redux) + - [Why does a reducer mutating the state prevent React-Redux from re-rendering a wrapped component?](#why-does-a-reducer-mutating-the-state-prevent-react-redux-from-re-rendering-a-wrapped-component) + - [Why does a selector mutating and returning a persistent object to `mapStateToProps` prevent React-Redux from re-rendering a wrapped component?](#why-does-a-selector-mutating-and-returning-a-persistent-object-to-mapstatetoprops-prevent-react-redux-from-re-rendering-a-wrapped-component) + - [How does immutability enable a shallow check to detect object mutations?](#how-does-immutability-enable-a-shallow-check-to-detect-object-mutations) + - [How can immutability in your reducers cause components to render unnecessarily?](#how-can-immutability-in-your-reducers-cause-components-to-render-unnecessarily) + - [How can immutability in mapStateToProps cause components to render unnecessarily?](#how-can-immutability-in-mapstatetoprops-cause-components-to-render-unnecessarily) - [What approaches are there for handling data immutability? Do I have to use Immutable.JS?](#what-approaches-are-there-for-handling-data-immutability-do-i-have-to-use-immutable-js) - [What are the issues with using JavaScript for immutable operations?](#what-are-the-issues-with-using-plain-javascript-for-immutable-operations) @@ -37,7 +54,7 @@ In particular, immutability in the context of a Web app enables sophisticated ch **Documentation** -- [Recipes: Prerequisite Reducer Concepts](http://redux.js.org/docs/recipes/reducers/PrerequisiteConcepts.html) +- [Recipes: Prerequisite Reducer Concepts](../recipes/structuring-reducers/PrerequisiteConcepts.md) **Discussions** @@ -69,11 +86,11 @@ Redux uses shallow equality checking in its `combineReducers` function to return **Documentation** -- [API: combineReducers](http://redux.js.org/docs/api/combineReducers.html) +- [API: combineReducers](../api/combineReducers.md) #### How does `combineReducers` use shallow equality checking? -The [suggested structure](http://redux.js.org/docs/faq/Reducers.html#reducers-share-state) for a Redux store is to split the state object into multiple "slices" or "domains" by key, and provide a separate reducer function to manage each individual data slice. +The [suggested structure](./Reducers.md#reducers-share-state) for a Redux store is to split the state object into multiple "slices" or "domains" by key, and provide a separate reducer function to manage each individual data slice. `combineReducers` makes working with this style of structure easier by taking a `reducers` argument that’s defined as a hash table comprising a set of key/value pairs, where each key is the name of a state slice, and the corresponding value is the reducer function that will act on it. @@ -106,8 +123,8 @@ This is worth emphasizing: _If the reducers all return the same `state` object p **Documentation** -- [API: combineReducers](http://redux.js.org/docs/api/combineReducers.html) -- [Redux FAQ - How do I share state between two reducers? do I have to use `combineReducers`?](http://redux.js.org/docs/faq/Reducers.html#reducers-share-state) +- [API: combineReducers](../api/combineReducers.md) +- [Redux FAQ - How do I share state between two reducers? do I have to use `combineReducers`?](./Reducers.md#reducers-share-state) **Video** @@ -117,7 +134,7 @@ This is worth emphasizing: _If the reducers all return the same `state` object p React-Redux uses shallow equality checking to determine whether the component it’s wrapping needs to be re-rendered. -To do this, it assumes that the wrapped component is pure; that is, that the component will produce the [same results given the same props and state](https://github.com/reduxjs/react-redux/blob/f4d55840a14601c3a5bdc0c3d741fc5753e87f66/docs/troubleshooting.md#my-views-arent-updating-when-something-changes-outside-of-redux). +To do this, it assumes that the wrapped component is pure; that is, that the component will produce the [same results given the same props and state](https://react-redux.js.org/troubleshooting#my-views-aren-t-updating-when-something-changes-outside-of-redux). By assuming the wrapped component is pure, it need only check whether the root state object or the values returned from `mapStateToProps` have changed. If they haven’t, the wrapped component does not need re-rendering. @@ -129,12 +146,12 @@ It then runs a shallow equality check on its reference to the root state object **Documentation** -- [React-Redux Bindings](http://redux.js.org/docs/basics/UsageWithReact.html) +- [React-Redux Bindings](https://react-redux.js.org) **Articles** -- [API: React-Redux’s connect function and `mapStateToProps`](https://github.com/reduxjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) -- [Troubleshooting: My views aren’t updating when something changes outside of Redux](https://github.com/reduxjs/react-redux/blob/f4d55840a14601c3a5bdc0c3d741fc5753e87f66/docs/troubleshooting.md#my-views-arent-updating-when-something-changes-outside-of-redux) +- [API: React-Redux’s connect function and `mapStateToProps`](https://react-redux.js.org/using-react-redux/connect-mapstate) +- [Redux FAQ: Why isn't my component re-rendering, or my `mapStateToProps` running?](./ReactRedux.md#why-isnt-my-component-re-rendering-or-my-mapstatetoprops-running) ### Why does React-Redux shallowly check each value within the props object returned from `mapStateToProp`? @@ -259,8 +276,8 @@ The store will still be updated with the new values for the root state, but beca **Documentation** -- [Recipes: Immutable Update Patterns](http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html) -- [Troubleshooting: Never mutate reducer arguments](http://redux.js.org/docs/Troubleshooting.html#never-mutate-reducer-arguments) +- [Recipes: Immutable Update Patterns](../recipes/structuring-reducers/ImmutableUpdatePatterns.md) +- [Troubleshooting: Never mutate reducer arguments](../Troubleshooting.md#never-mutate-reducer-arguments) ### Why does a reducer mutating the state prevent React-Redux from re-rendering a wrapped component? @@ -272,7 +289,7 @@ Because React-Redux performs a shallow check on the root state object to determi **Documentation** -- [Troubleshooting: My views aren’t updating when something changes outside of Redux](https://github.com/reduxjs/react-redux/blob/f4d55840a14601c3a5bdc0c3d741fc5753e87f66/docs/troubleshooting.md#my-views-arent-updating-when-something-changes-outside-of-redux) +- [Troubleshooting: My views aren’t updating when something changes outside of Redux](https://react-redux.js.org/troubleshooting#my-views-aren-t-updating-when-something-changes-outside-of-redux) ### Why does a selector mutating and returning a persistent object to `mapStateToProps` prevent React-Redux from re-rendering a wrapped component? @@ -436,7 +453,7 @@ JavaScript was never designed to provide guaranteed immutable operations. Accord With JavaScript, you can accidentally mutate an object (such as the Redux state tree) quite easily without realizing it. For example, updating deeply nested properties, creating a new _reference_ to an object instead of a new object, or performing a shallow copy rather than a deep copy, can all lead to inadvertent object mutations, and can trip up even the most experienced JavaScript coder. -To avoid these issues, ensure you follow the recommended [immutable update patterns for ES6](http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html). +To avoid these issues, ensure you follow the recommended [immutable update patterns for ES6](../recipes/structuring-reducers/ImmutableUpdatePatterns.md). ### Verbose Code @@ -456,7 +473,7 @@ For copying very large objects, [plain JavaScript can be over 100 times slower]( **Documentation** -- [Immutable Update Patterns for ES6](http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html) +- [Immutable Update Patterns for ES6](../recipes/structuring-reducers/ImmutableUpdatePatterns.md) **Articles** diff --git a/docs/faq/Miscellaneous.md b/docs/faq/Miscellaneous.md index 985a1bae18..b7f2a27e40 100644 --- a/docs/faq/Miscellaneous.md +++ b/docs/faq/Miscellaneous.md @@ -1,3 +1,10 @@ +--- +id: miscellaneous +title: Miscellaneous +sidebar_label: Miscellaneous +hide_title: true +--- + # Redux FAQ: Miscellaneous ## Table of Contents @@ -22,7 +29,7 @@ And many, many more! The Redux Addons Catalog has **[a list of Redux-based appli **Documentation** -- [Introduction: Examples](/docs/introduction/Examples.md) +- [Introduction: Examples](../introduction/Examples.md) **Discussions** diff --git a/docs/faq/OrganizingState.md b/docs/faq/OrganizingState.md index 14ce80c768..ba6ad60381 100644 --- a/docs/faq/OrganizingState.md +++ b/docs/faq/OrganizingState.md @@ -1,3 +1,10 @@ +--- +id: organizing-state +title: Organizing State +sidebar_label: Organizing State +hide_title: true +--- + # Redux FAQ: Organizing State ## Table of Contents @@ -5,6 +12,7 @@ - [Do I have to put all my state into Redux? Should I ever use React's setState()?](#do-i-have-to-put-all-my-state-into-redux-should-i-ever-use-reacts-setstate) - [Can I put functions, promises, or other non-serializable items in my store state?](#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state) - [How do I organize nested or duplicate data in my state?](#how-do-i-organize-nested-or-duplicate-data-in-my-state) +- [Should I put form state or other UI state in my store?](#should-i-put-form-state-or-other-ui-state-in-my-store) ## Organizing State @@ -21,6 +29,7 @@ Some common rules of thumb for determining what kind of data should be put into - Is the same data being used to drive multiple components? - Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)? - Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)? +- Do you want to keep this data consistent while hot-reloading UI components (which may lose their internal state when swapped)? There are a number of community packages that implement various approaches for storing per-component state in a Redux store instead, such as [redux-ui](https://github.com/tonyhb/redux-ui), [redux-component](https://github.com/tomchentw/redux-component), [redux-react-local](https://github.com/threepointone/redux-react-local), and more. It's also possible to apply Redux's principles and concept of reducers to the task of updating local component state as well, along the lines of `this.setState( (previousState) => reducer(previousState, someAction))`. @@ -77,10 +86,10 @@ Data with IDs, nesting, or relationships should generally be stored in a “norm **Documentation** -- [Advanced: Async Actions](/docs/advanced/AsyncActions.md) -- [Examples: Real World example](/docs/introduction/Examples.md#real-world) -- [Recipes: Structuring Reducers - Prerequisite Concepts](/docs/recipes/reducers/PrerequisiteConcepts.md#normalizing-data) -- [Recipes: Structuring Reducers - Normalizing State Shape](/docs/recipes/reducers/NormalizingStateShape.md) +- [Advanced: Async Actions](../advanced/AsyncActions.md) +- [Examples: Real World example](../introduction/Examples.md#real-world) +- [Recipes: Structuring Reducers - Prerequisite Concepts](../recipes/structuring-reducers/PrerequisiteConcepts.md#normalizing-data) +- [Recipes: Structuring Reducers - Normalizing State Shape](../recipes/structuring-reducers/NormalizingStateShape.md) - [Examples: Tree View](https://github.com/reduxjs/redux/tree/master/examples/tree-view) **Articles** @@ -100,3 +109,29 @@ Data with IDs, nesting, or relationships should generally be stored in a “norm - [Twitter: state shape should be normalized](https://twitter.com/dan_abramov/status/715507260244496384) - [Stack Overflow: How to handle tree-shaped entities in Redux reducers?](http://stackoverflow.com/questions/32798193/how-to-handle-tree-shaped-entities-in-redux-reducers) - [Stack Overflow: How to optimize small updates to props of nested components in React + Redux?](http://stackoverflow.com/questions/37264415/how-to-optimize-small-updates-to-props-of-nested-component-in-react-redux) + +### Should I put form state or other UI state in my store? + +The [same rules of thumb for deciding what should go in the Redux store](#do-i-have-to-put-all-my-state-into-redux-should-i-ever-use-reacts-setstate) apply for this question as well. + +**Based on those rules of thumb, most form state doesn't need to go into Redux**, as it's probably not being shared between components. However, that decision is always going to be specific to you and your application. You might choose to keep some form state in Redux because you are editing data that came from the store originally, or because you do need to see the work-in-progress values reflected in other components elsewhere in the application. On the other hand, it may be a lot simpler to keep the form state local to the component, and only dispatch an action to put the data in the store once the user is done with the form. + +Based on this, in most cases you probably don't need a Redux-based form management library either. We suggest trying these approaches, in this order: + +- Even if the data is coming from the Redux store, start by writing your form logic by hand. It's likely this is all you'll need. (See [**Gosha Arinich's posts on working with forms in React**](https://goshakkk.name/on-forms-react/) for some excellent guidance on this.) +- If you decide that writing forms "manually" is too difficult, try a React-based form library like [Formik](https://github.com/jaredpalmer/formik) or [React-Final-Form](https://github.com/final-form/react-final-form). +- If you are absolutely sure you _must_ use a Redux-based form library because the other approaches aren't sufficient, then you may finally want to look at [Redux-Form](https://github.com/erikras/redux-form) and [React-Redux-Form](https://github.com/davidkpiano/react-redux-form). + +If you are keeping form state in Redux, you should take some time to consider performance characteristics. Dispatching an action on every keystroke of a text input probably isn't worthwhile, and you may want to look into [ways to buffer keystrokes to keep changes local before dispatching](https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/). As always, take some time to analyze the overall performance needs of your own application. + +Other kinds of UI state follow these rules of thumb as well. The classic example is tracking an `isDropdownOpen` flag. In most situations, the rest of the app doesn't care about this, so in most cases it should stay in component state. However, depending on your application, it may make sense to use Redux to [manage dialogs and other popups](https://blog.isquaredsoftware.com/2017/07/practical-redux-part-10-managing-modals/), tabs, expanding panels, and so on. + +#### Further Information + +**Articles** + +- [Gosha Arinich: Writings on Forms in React](https://goshakkk.name/on-forms-react/) +- [Practical Redux, Part 6: Connected Lists and Forms](https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/) +- [Practical Redux, Part 7: Form Change Handling](https://blog.isquaredsoftware.com/2017/01/practical-redux-part-7-forms-editing-reducers/) +- [Practical Redux, Part 10: Managing Modals and Context Menus](https://blog.isquaredsoftware.com/2017/07/practical-redux-part-10-managing-modals/) +- [React/Redux Links: Redux UI Management](https://github.com/markerikson/react-redux-links/blob/master/redux-ui-management.md) diff --git a/docs/faq/Performance.md b/docs/faq/Performance.md index 245bcd7a2d..80551cd985 100644 --- a/docs/faq/Performance.md +++ b/docs/faq/Performance.md @@ -1,9 +1,16 @@ +--- +id: performance +title: Performance +sidebar_label: Performance +hide_title: true +--- + # Redux FAQ: Performance ## Table of Contents - [How well does Redux “scale” in terms of performance and architecture?](#how-well-does-redux-scale-in-terms-of-performance-and-architecture) -- [Won't calling “all my reducers” for each action be slow?](#wont-calling-all-my-reducers-for-each-action-be-slow) +- [Won't calling “all my reducers” for each action be slow?](#won-t-calling-all-my-reducers-for-each-action-be-slow) - [Do I have to deep-clone my state in a reducer? Isn't copying my state going to be slow?](#do-i-have-to-deep-clone-my-state-in-a-reducer-isnt-copying-my-state-going-to-be-slow) - [How can I reduce the number of store update events?](#how-can-i-reduce-the-number-of-store-update-events) - [Will having “one state tree” cause memory problems? Will dispatching many actions take up memory?](#will-having-one-state-tree-cause-memory-problems-will-dispatching-many-actions-take-up-memory) @@ -27,7 +34,7 @@ As for architecture, anecdotal evidence is that Redux works well for varying pro **Documentation** -- [Recipes: Structuring Reducers - Normalizing State Shape](/docs/recipes/reducers/NormalizingStateShape.md) +- [Recipes: Structuring Reducers - Normalizing State Shape](../recipes/structuring-reducers/NormalizingStateShape.md) **Articles** @@ -88,8 +95,8 @@ However, you _do_ need to create a copied and updated object for each level of n **Documentation** -- [Recipes: Structuring Reducers - Prerequisite Concepts](/docs/recipes/reducers/PrerequisiteConcepts.md) -- [Recipes: Structuring Reducers - Immutable Update Patterns](/docs/recipes/reducers/ImmutableUpdatePatterns.md) +- [Recipes: Structuring Reducers - Prerequisite Concepts](../recipes/structuring-reducers/PrerequisiteConcepts.md) +- [Recipes: Structuring Reducers - Immutable Update Patterns](../recipes/structuring-reducers/ImmutableUpdatePatterns.md) **Discussions** @@ -129,7 +136,7 @@ Redux does not store a history of actions itself. However, the Redux DevTools do **Documentation** -- [Docs: Async Actions](/docs/advanced/AsyncActions.md) +- [Docs: Async Actions](../advanced/AsyncActions.md) **Discussions** @@ -149,7 +156,7 @@ First, only cache as much data as the user needs. If your application displays a Second, cache an abbreviated form of a record when possible. Sometimes a record includes data that is not relevant to the user. If the application does not depend on this data, it can be omitted from the cache. -Third, only cache a single copy of a record. This is especially important when records contain copies of other records. Cache a unique copy for each record and replace each nested copy with a reference. This is called normalization. Normalization is the preferred approach to storing relational data for [several reasons](/docs/recipes/reducers/NormalizingStateShape.html#designing-a-normalized-state), including efficient memory consumption. +Third, only cache a single copy of a record. This is especially important when records contain copies of other records. Cache a unique copy for each record and replace each nested copy with a reference. This is called normalization. Normalization is the preferred approach to storing relational data for [several reasons](../recipes/reducers/NormalizingStateShape.md#designing-a-normalized-state), including efficient memory consumption. #### Further information diff --git a/docs/faq/ReactRedux.md b/docs/faq/ReactRedux.md index 4edb88a0db..0f63e0d082 100644 --- a/docs/faq/ReactRedux.md +++ b/docs/faq/ReactRedux.md @@ -1,7 +1,15 @@ +--- +id: react-redux +title: React Redux +sidebar_label: React Redux +hide_title: true +--- + # Redux FAQ: React Redux ## Table of Contents +- [Why should I use React-Redux?](#why-should-i-use-react-redux) - [Why isn't my component re-rendering, or my mapStateToProps running?](#why-isnt-my-component-re-rendering-or-my-mapstatetoprops-running) - [Why is my component re-rendering too often?](#why-is-my-component-re-rendering-too-often) - [How can I speed up my mapStateToProps?](#how-can-i-speed-up-my-mapstatetoprops) @@ -10,6 +18,26 @@ ## React Redux +### Why should I use React-Redux? + +Redux itself is a standalone library that can be used with any UI layer or framework, including React, Angular, Vue, Ember, and vanilla JS. Although Redux and React are commonly used together, they are independent of each other. + +If you are using Redux with any kind of UI framework, you will normally use a "UI binding" library to tie Redux together with your UI framework, rather than directly interacting with the store from your UI code. + +**React-Redux is the official Redux UI binding library for React**. If you are using Redux and React together, you should also use React-Redux to bind these two libraries. + +While it is possible to write Redux store subscription logic by hand, doing so would become very repetitive. In addition, optimizing UI performance would require complicated logic. + +The process of subscribing to the store, checking for updated data, and triggering a re-render can be made more generic and reusable. **A UI binding library like React-Redux handles the store interaction logic, so you don't have to write that code yourself.** + +Overall, React-Redux encourages good React architecture, and implements complex performance optimizations for you. It is also kept up-to-date with the latest API changes from Redux and React. + +#### Further Information + +**Documentation** + +- **[React-Redux docs: Why Use React-Redux?](https://react-redux.js.org/introduction/why-use-react-redux)** + ### Why isn't my component re-rendering, or my mapStateToProps running? Accidentally mutating or modifying your state directly is by far the most common reason why components do not re-render after an action has been dispatched. Redux expects that your reducers will update their state “immutably”, which effectively means always making copies of your data, and applying your changes to the copies. If you return the same object from a reducer, Redux assumes that nothing has been changed, even if you made changes to its contents. Similarly, React Redux tries to improve performance by doing shallow equality reference checks on incoming props in `shouldComponentUpdate`, and if all references are the same, `shouldComponentUpdate` returns `false` to skip actually updating your original component. @@ -26,11 +54,11 @@ Note that “updating data immutably” does _not_ mean that you must use [Immut **Documentation** -- [Troubleshooting](/docs/Troubleshooting.md) -- [React Redux: Troubleshooting](https://github.com/reduxjs/react-redux/blob/master/docs/troubleshooting.md) -- [Recipes: Using the Object Spread Operator](/docs/recipes/UsingObjectSpreadOperator.md) -- [Recipes: Structuring Reducers - Prerequisite Concepts](/docs/recipes/reducers/PrerequisiteConcepts.md) -- [Recipes: Structuring Reducers - Immutable Update Patterns](/docs/recipes/reducers/ImmutableUpdatePatterns.md) +- [Troubleshooting](../Troubleshooting.md) +- [React Redux: Troubleshooting](https://react-redux.js.org/troubleshooting) +- [Recipes: Using the Object Spread Operator](../recipes/UsingObjectSpreadOperator.md) +- [Recipes: Structuring Reducers - Prerequisite Concepts](../recipes/structuring-reducers/PrerequisiteConcepts.md) +- [Recipes: Structuring Reducers - Immutable Update Patterns](../recipes/structuring-reducers/ImmutableUpdatePatterns.md) **Articles** @@ -67,7 +95,7 @@ For non-connected components, you may want to check what props are being passed **Documentation** -- [FAQ: Performance - Scaling](/docs/faq/Performance.md#performance-scaling) +- [FAQ: Performance - Scaling](./Performance.md#performance-scaling) **Articles** @@ -93,7 +121,7 @@ While React Redux does work to minimize the number of times that your `mapStateT **Documentation** -- [Recipes: Computed Derived Data](/docs/recipes/ComputingDerivedData.md) +- [Recipes: Computed Derived Data](../recipes/ComputingDerivedData.md) **Articles** @@ -114,7 +142,7 @@ If you do not provide your own `mapDispatchToProps` function when calling `conne **Documentation** -- [React Redux API: connect()](https://github.com/reduxjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) +- [React Redux API: connect()](https://react-redux.js.org/api#connect) **Discussions** @@ -139,8 +167,8 @@ In general, try to find a balance between understandable data flow and areas of **Documentation** -- [Basics: Usage with React](/docs/basics/UsageWithReact.md) -- [FAQ: Performance - Scaling](/docs/faq/Performance.md#performance-scaling) +- [Basics: Usage with React](../basics/UsageWithReact.md) +- [FAQ: Performance - Scaling](../faq/Performance.md#performance-scaling) **Articles** diff --git a/docs/faq/Reducers.md b/docs/faq/Reducers.md index ad8f142838..9c5d3e6599 100644 --- a/docs/faq/Reducers.md +++ b/docs/faq/Reducers.md @@ -1,3 +1,10 @@ +--- +id: reducers +title: Reducers +sidebar_label: Reducers +hide_title: true +--- + # Redux FAQ: Reducers ## Table of Contents @@ -9,13 +16,13 @@ ### How do I share state between two reducers? Do I have to use `combineReducers`? -The suggested structure for a Redux store is to split the state object into multiple “slices” or “domains” by key, and provide a separate reducer function to manage each individual data slice. This is similar to how the standard Flux pattern has multiple independent stores, and Redux provides the [`combineReducers`](/docs/api/combineReducers.md) utility function to make this pattern easier. However, it's important to note that `combineReducers` is _not_ required—it is simply a utility function for the common use case of having a single reducer function per state slice, with plain JavaScript objects for the data. +The suggested structure for a Redux store is to split the state object into multiple “slices” or “domains” by key, and provide a separate reducer function to manage each individual data slice. This is similar to how the standard Flux pattern has multiple independent stores, and Redux provides the [`combineReducers`](../api/combineReducers.md) utility function to make this pattern easier. However, it's important to note that `combineReducers` is _not_ required—it is simply a utility function for the common use case of having a single reducer function per state slice, with plain JavaScript objects for the data. Many users later want to try to share data between two reducers, but find that `combineReducers` does not allow them to do so. There are several approaches that can be used: - If a reducer needs to know data from another slice of state, the state tree shape may need to be reorganized so that a single reducer is handling more of the data. - You may need to write some custom functions for handling some of these actions. This may require replacing `combineReducers` with your own top-level reducer function. You can also use a utility such as [reduce-reducers](https://github.com/acdlite/reduce-reducers) to run `combineReducers` to handle most actions, but also run a more specialized reducer for specific actions that cross state slices. -- [Async action creators](/docs/advanced/AsyncActions.md#async-action-creators) such as [redux-thunk](https://github.com/gaearon/redux-thunk) have access to the entire state through `getState()`. An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice. +- [Async action creators](../advanced/AsyncActions.md#async-action-creators) such as [redux-thunk](https://github.com/gaearon/redux-thunk) have access to the entire state through `getState()`. An action creator can retrieve additional data from the state and put it in an action, so that each reducer has enough information to update its own state slice. In general, remember that reducers are just functions—you can organize them and subdivide them any way you want, and you are encouraged to break them down into smaller, reusable functions (“reducer composition”). While you do so, you may pass a custom third argument from a parent reducer if a child reducer needs additional data to calculate its next state. You just need to make sure that together they follow the basic rules of reducers: `(state, action) => newState`, and update state immutably rather than mutating it directly. @@ -23,8 +30,8 @@ In general, remember that reducers are just functions—you can organize them an **Documentation** -- [API: combineReducers](/docs/api/combineReducers.md) -- [Recipes: Structuring Reducers](/docs/recipes/StructuringReducers.md) +- [API: combineReducers](../api/combineReducers.md) +- [Recipes: Structuring Reducers](../recipes/structuring-reducers/StructuringReducers.md) **Discussions** @@ -42,8 +49,8 @@ No. You are welcome to use any approach you'd like to respond to an action in a **Documentation** -- [Recipes: Reducing Boilerplate](/docs/recipes/ReducingBoilerplate.md) -- [Recipes: Structuring Reducers - Splitting Reducer Logic](/docs/recipes/reducers/SplittingReducerLogic.md) +- [Recipes: Reducing Boilerplate](../recipes/ReducingBoilerplate.md) +- [Recipes: Structuring Reducers - Splitting Reducer Logic](../recipes/structuring-reducers/SplittingReducerLogic.md) **Discussions** diff --git a/docs/faq/StoreSetup.md b/docs/faq/StoreSetup.md index 8d5becce6c..3dff05ceb0 100644 --- a/docs/faq/StoreSetup.md +++ b/docs/faq/StoreSetup.md @@ -1,3 +1,10 @@ +--- +id: store-setup +title: Store Setup +sidebar_label: Store Setup +hide_title: true +--- + # Redux FAQ: Store Setup ## Table of Contents @@ -29,7 +36,7 @@ With [React Redux](https://github.com/reduxjs/react-redux), the wrapper classes **Documentation** -- [API: Store](/docs/api/Store.md) +- [API: Store](../api/Store.md) **Discussions** @@ -48,8 +55,8 @@ This chain of middleware is defined by the arguments passed to the `applyMiddlew **Documentation** -- [Advanced: Middleware](/docs/advanced/Middleware.md) -- [API: applyMiddleware](/docs/api/applyMiddleware.md) +- [Advanced: Middleware](../advanced/Middleware.md) +- [API: applyMiddleware](../api/applyMiddleware.md) **Discussions** @@ -69,8 +76,8 @@ The new state is not passed to the listeners in order to simplify implementing s **Documentation** -- [Basics: Store](/docs/basics/Store.md) -- [API: Store](/docs/api/Store.md) +- [Basics: Store](../basics/Store.md) +- [API: Store](../api/Store.md) **Discussions** diff --git a/docs/introduction/CoreConcepts.md b/docs/introduction/CoreConcepts.md index 85a8301498..7fa8ec2c81 100644 --- a/docs/introduction/CoreConcepts.md +++ b/docs/introduction/CoreConcepts.md @@ -1,3 +1,10 @@ +--- +id: core-concepts +title: Core Concepts +sidebar_label: Core Concepts +hide_title: true +--- + # Core Concepts Imagine your app’s state is described as a plain object. For example, the state of a todo app might look like this: diff --git a/docs/introduction/Ecosystem.md b/docs/introduction/Ecosystem.md index 1c567cdb57..9d5eafa600 100644 --- a/docs/introduction/Ecosystem.md +++ b/docs/introduction/Ecosystem.md @@ -1,3 +1,10 @@ +--- +id: ecosystem +title: Ecosystem +sidebar_label: Ecosystem +hide_title: true +--- + # Ecosystem Redux is a tiny library, but its contracts and APIs are carefully chosen to spawn an ecosystem of tools and extensions, and the community has created a wide variety of helpful addons, libraries, and tools. You don't need to use any of these addons to use Redux, but they can help make it easier to implement features and solve problems in your application. @@ -34,6 +41,7 @@ This page lists some of the Redux-related addons that the Redux maintainers have - [Component State and Encapsulation](#component-state-and-encapsulation) - [Dev Tools](#dev-tools) - [Debuggers and Viewers](#debuggers-and-viewers) + - [DevTools Monitors](#devtools-monitors) - [Logging](#logging) - [Mutation Detection](#mutation-detection) - [Testing](#testing) @@ -56,7 +64,7 @@ Angular 2+ bindings for Redux **[ember-redux/ember-redux](https://github.com/ember-redux/ember-redux)** Ember bindings for Redux -**[glimmer-redux/glimmer-redux](glimmer-redux/glimmer-redux)** +**[glimmer-redux/glimmer-redux](https://github.com/glimmer-redux/glimmer-redux)** Redux bindings for Ember's Glimmer component engine **[tur-nr/polymer-redux](https://github.com/tur-nr/polymer-redux)** @@ -69,7 +77,7 @@ Redux bindings for custom elements #### Reducer Combination -**[ryo33/combineSectionReducers](https://github.com/ryo33/combine-section-reducers)** +**[ryo33/combineSectionReducers](https://gitlab.com/ryo33/combine-section-reducers)** An expanded version of `combineReducers`, which allows passing `state` as a third argument to all slice reducers. **[KodersLab/topologically-combine-reducers](https://github.com/KodersLab/topologically-combine-reducers)** @@ -798,8 +806,8 @@ Makes integration and unit testing of sagas a breeze ## Routing -**[ReactTraining/react-router-redux](https://github.com/ReactTraining/react-router/tree/master/packages/react-router-redux)** -Keep your state in sync with your router +**[supasate/connected-react-router](https://github.com/supasate/connected-react-router)** +Synchronize React Router 4 state with your Redux store. **[FormidableLabs/redux-little-router](https://github.com/FormidableLabs/redux-little-router)** A tiny router for Redux applications that lets the URL do the talking diff --git a/docs/introduction/Examples.md b/docs/introduction/Examples.md index 69e57a7b1c..e45db18e7b 100644 --- a/docs/introduction/Examples.md +++ b/docs/introduction/Examples.md @@ -1,87 +1,122 @@ +--- +id: examples +title: Examples +sidebar_label: Examples +hide_title: true +--- + # Examples -Redux is distributed with a few examples in its [source code](https://github.com/reactjs/redux/tree/master/examples). Most of these examples are also on [CodeSandbox](https://codesandbox.io), an online editor that lets you play with the examples online. +Redux is distributed with a few examples in its [source code](https://github.com/reduxjs/redux/tree/master/examples). Most of these examples are also on [CodeSandbox](https://codesandbox.io), an online editor that lets you play with the examples online. ## Counter Vanilla -Run the [Counter Vanilla](https://github.com/reactjs/redux/tree/master/examples/counter-vanilla) example: +Run the [Counter Vanilla](https://github.com/reduxjs/redux/tree/master/examples/counter-vanilla) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/counter-vanilla open index.html ``` +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/counter-vanilla): + + + It does not require a build system or a view framework and exists to show the raw Redux API used with ES5. ## Counter -Run the [Counter](https://github.com/reactjs/redux/tree/master/examples/counter) example: +Run the [Counter](https://github.com/reduxjs/redux/tree/master/examples/counter) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/counter npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/counter): +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/counter): -{% embed data="{\"url\":\"https://codesandbox.io/embed/github/reactjs/redux/tree/master/examples/counter\",\"type\":\"link\",\"title\":\"CodeSandbox\",\"description\":\"CodeSandbox is an online editor tailored for web applications.\",\"icon\":{\"type\":\"icon\",\"url\":\"https://codesandbox.io/favicon.ico\",\"aspectRatio\":0},\"thumbnail\":{\"type\":\"thumbnail\",\"url\":\"https://codesandbox.io/static/img/banner.png\",\"width\":1200,\"height\":630,\"aspectRatio\":0.525}}" %} + -This is the most basic example of using Redux together with React. For simplicity, it re-renders the React component manually when the store changes. In real projects, you will likely want to use the highly performant [React Redux](https://github.com/reactjs/react-redux) bindings instead. +This is the most basic example of using Redux together with React. For simplicity, it re-renders the React component manually when the store changes. In real projects, you will likely want to use the highly performant [React Redux](https://github.com/reduxjs/react-redux) bindings instead. This example includes tests. ## Todos -Run the [Todos](https://github.com/reactjs/redux/tree/master/examples/todos) example: +Run the [Todos](https://github.com/reduxjs/redux/tree/master/examples/todos) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/todos npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/todos). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos): -This is the best example to get a deeper understanding of how the state updates work together with components in Redux. It shows how reducers can delegate handling actions to other reducers, and how you can use [React Redux](https://github.com/reactjs/react-redux) to generate container components from your presentational components. + + +This is the best example to get a deeper understanding of how the state updates work together with components in Redux. It shows how reducers can delegate handling actions to other reducers, and how you can use [React Redux](https://github.com/reduxjs/react-redux) to generate container components from your presentational components. This example includes tests. ## Todos with Undo -Run the [Todos with Undo](https://github.com/reactjs/redux/tree/master/examples/todos-with-undo) example: +Run the [Todos with Undo](https://github.com/reduxjs/redux/tree/master/examples/todos-with-undo) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/todos-with-undo npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/todos-with-undo). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos-with-undo): + + This is a variation on the previous example. It is almost identical, but additionally shows how wrapping your reducer with [Redux Undo](https://github.com/omnidan/redux-undo) lets you add a Undo/Redo functionality to your app with a few lines of code. -## TodoMVC +## Todos w/ Flow -Run the [TodoMVC](https://github.com/reactjs/redux/tree/master/examples/todomvc) example: +Run the [Todos w/ Flow](https://github.com/reduxjs/redux/tree/master/examples/todos-flow) example: +```sh +git clone https://github.com/reduxjs/redux.git + +cd redux/examples/todos-flow +npm install +npm start ``` -git clone https://github.com/reactjs/redux.git + +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos-flow): + + + +This is like the previous Todos examples, but shows how to use Redux in conjunction with [Flow](https://flow.org/). + +## TodoMVC + +Run the [TodoMVC](https://github.com/reduxjs/redux/tree/master/examples/todomvc) example: + +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/todomvc npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/todomvc). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todomvc): + + This is the classical [TodoMVC](http://todomvc.com/) example. It's here for the sake of comparison, but it covers the same points as the Todos example. @@ -89,33 +124,37 @@ This example includes tests. ## Shopping Cart -Run the [Shopping Cart](https://github.com/reactjs/redux/tree/master/examples/shopping-cart) example: +Run the [Shopping Cart](https://github.com/reduxjs/redux/tree/master/examples/shopping-cart) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/shopping-cart npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/shopping-cart). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/shopping-cart): + + This example shows important idiomatic Redux patterns that become important as your app grows. In particular, it shows how to store entities in a normalized way by their IDs, how to compose reducers on several levels, and how to define selectors alongside the reducers so the knowledge about the state shape is encapsulated. It also demonstrates logging with [Redux Logger](https://github.com/fcomb/redux-logger) and conditional dispatching of actions with [Redux Thunk](https://github.com/gaearon/redux-thunk) middleware. ## Tree View -Run the [Tree View](https://github.com/reactjs/redux/tree/master/examples/tree-view) example: +Run the [Tree View](https://github.com/reduxjs/redux/tree/master/examples/tree-view) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/tree-view npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/tree-view). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/tree-view): + + This example demonstrates rendering a deeply nested tree view and representing its state in a normalized form so it is easy to update from reducers. Good rendering performance is achieved by the container components granularly subscribing only to the tree nodes that they render. @@ -123,26 +162,28 @@ This example includes tests. ## Async -Run the [Async](https://github.com/reactjs/redux/tree/master/examples/async) example: +Run the [Async](https://github.com/reduxjs/redux/tree/master/examples/async) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/async npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/async). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/async): + + This example includes reading from an asynchronous API, fetching data in response to user input, showing loading indicators, caching the response, and invalidating the cache. It uses [Redux Thunk](https://github.com/gaearon/redux-thunk) middleware to encapsulate asynchronous side effects. ## Universal -Run the [Universal](https://github.com/reactjs/redux/tree/master/examples/universal) example: +Run the [Universal](https://github.com/reduxjs/redux/tree/master/examples/universal) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/universal npm install @@ -153,20 +194,23 @@ This is a basic demonstration of [server rendering](../recipes/ServerRendering.m ## Real World -Run the [Real World](https://github.com/reactjs/redux/tree/master/examples/real-world) example: +Run the [Real World](https://github.com/reduxjs/redux/tree/master/examples/real-world) example: -``` -git clone https://github.com/reactjs/redux.git +```sh +git clone https://github.com/reduxjs/redux.git cd redux/examples/real-world npm install npm start ``` -Or check out the [sandbox](https://codesandbox.io/s/github/reactjs/redux/tree/master/examples/real-world). +Or check out the [sandbox](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/real-world): + + This is the most advanced example. It is dense by design. It covers keeping fetched entities in a normalized cache, implementing a custom middleware for API calls, rendering partially loaded data, pagination, caching responses, displaying error messages, and routing. Additionally, it includes Redux DevTools. ## More Examples -You can find more examples in [Awesome Redux](https://github.com/xgrommx/awesome-redux). +You can find more examples in the [Redux Apps and Examples](https://github.com/markerikson/redux-ecosystem-links/blob/master/apps-and-examples.md) +page of the [Redux Addons Catalog](https://github.com/markerikson/redux-ecosystem-links). diff --git a/docs/introduction/GettingStarted.md b/docs/introduction/GettingStarted.md new file mode 100644 index 0000000000..549ee16d6a --- /dev/null +++ b/docs/introduction/GettingStarted.md @@ -0,0 +1,178 @@ +--- +id: getting-started +title: Getting Started with Redux +sidebar_label: Getting Started with Redux +hide_title: true +--- + +# Getting Started with Redux + +Redux is a predictable state container for JavaScript apps. + +It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test. On top of that, it provides a great developer experience, such as [live code editing combined with a time traveling debugger](https://github.com/reduxjs/redux-devtools). + +You can use Redux together with [React](https://reactjs.org), or with any other view library. It is tiny (2kB, including dependencies), but has a large ecosystem of addons available. + +## Installation + +Redux is available as a package on NPM for use with a module bundler or in a Node application: + +```bash +npm install --save redux +``` + +It is also available as a precompiled UMD package that defines a `window.Redux` global variable. The UMD package can be used as a [`