Skip to content

Commit

Permalink
Merge pull request #4625 from reduxjs/docs/5.0-docs-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Nov 25, 2023
2 parents 0d7ef2c + 173ff78 commit e124f0b
Show file tree
Hide file tree
Showing 46 changed files with 1,643 additions and 403 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ This repo uses Yarn 3 for all package management. Please ensure that Yarn 1.x is

#### Building Redux

Running the `build` task will create a CommonJS module-per-module build, a ES Modules build and a UMD build.
Running the `build` task will build the artifacts into the `./dist` folder

```sh
yarn build
Expand Down
163 changes: 27 additions & 136 deletions README.md

Large diffs are not rendered by default.

28 changes: 10 additions & 18 deletions docs/api/Store.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,11 @@ description: 'API > Store: the core Redux store methods'
# Store

A store holds the whole [state tree](../understanding/thinking-in-redux/Glossary.md#state) of your application.
The only way to change the state inside it is to dispatch an [action](../understanding/thinking-in-redux/Glossary.md#action) on it.
The only way to change the state inside it is to dispatch an [action](../understanding/thinking-in-redux/Glossary.md#action) on it, which triggers the [root reducer function](../understanding/thinking-in-redux/Glossary.md#reducer) to calculate the new state.

A store is not a class. It's just an object with a few methods on it.
To create it, pass your root [reducing function](../understanding/thinking-in-redux/Glossary.md#reducer) to [`createStore`](createStore.md).

> ##### A Note for Flux Users
>
> If you're coming from Flux, there is a single important difference you need to understand. Redux doesn't have a Dispatcher or support many stores. **Instead, there is just a single store with a single root [reducing function](../understanding/thinking-in-redux/Glossary.md#reducer).** As your app grows, instead of adding stores, you split the root reducer into smaller reducers independently operating on the different parts of the state tree. You can use a helper like [`combineReducers`](combineReducers.md) to combine them. This is similar to how there is just one root component in a React app, but it is composed out of many small components.
### Store Methods

- [`getState()`](#getstate)
- [`dispatch(action)`](#dispatchaction)
- [`subscribe(listener)`](#subscribelistener)
- [`replaceReducer(nextReducer)`](#replacereducernextreducer)
To create a store, **pass your root [reducer function](../understanding/thinking-in-redux/Glossary.md#reducer) to Redux Toolkit's [`configureStore` method](https://redux-toolkit.js.org/api/configureStore)**, which will set up a Redux store with a good default configuration. (Alternately, if you're not yet using Redux Toolkit, you can use the original [`createStore`](createStore.md) method, but we encourage you to [migrate your code to use Redux Toolkit](../usage/migrating-to-modern-redux.mdx) as soon as possible)

## Store Methods

Expand All @@ -42,13 +32,15 @@ _(any)_: The current state tree of your application.

Dispatches an action. This is the only way to trigger a state change.

The store's reducing function will be called with the current [`getState()`](#getState) result and the given `action` synchronously. Its return value will be considered the next state. It will be returned from [`getState()`](#getState) from now on, and the change listeners will immediately be notified.
The store's reducer function will be called with the current [`getState()`](#getState) result and the given `action` synchronously. Its return value will be considered the next state. It will be returned from [`getState()`](#getState) from now on, and the change listeners will immediately be notified.

:::caution

If you attempt to call `dispatch` from inside the [reducer](../understanding/thinking-in-redux/Glossary.md#reducer), it will throw with an error saying "Reducers may not dispatch actions." Reducers are pure functions - they can _only_ return a new state value and must not have side effects (and dispatching is a side effect).

In Redux, subscriptions are called after the root reducer has returned the new state, so you _may_ dispatch in the subscription listeners. You are only disallowed to dispatch inside the reducers because they must have no side effects. If you want to cause a side effect in response to an action, the right place to do this is in the potentially async [action creator](../understanding/thinking-in-redux/Glossary.md#action-creator).

> ##### A Note for Flux Users
>
> If you attempt to call `dispatch` from inside the [reducer](../understanding/thinking-in-redux/Glossary.md#reducer), it will throw with an error saying “Reducers may not dispatch actions.” This is similar to “Cannot dispatch in a middle of dispatch” error in Flux, but doesn't cause the problems associated with it. In Flux, a dispatch is forbidden while Stores are handling the action and emitting updates. This is unfortunate because it makes it impossible to dispatch actions from component lifecycle hooks or other benign places.
>
> In Redux, subscriptions are called after the root reducer has returned the new state, so you _may_ dispatch in the subscription listeners. You are only disallowed to dispatch inside the reducers because they must have no side effects. If you want to cause a side effect in response to an action, the right place to do this is in the potentially async [action creator](../understanding/thinking-in-redux/Glossary.md#action-creator).
:::

#### Arguments

Expand Down
51 changes: 24 additions & 27 deletions docs/api/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,41 @@ title: API Reference

# API Reference

The Redux API surface is tiny. Redux defines a set of contracts for you to implement (such as [reducers](../understanding/thinking-in-redux/Glossary.md#reducer)) and provides a few helper functions to tie these contracts together.
This section documents the original Redux core API. The Redux core is small - it defines a set of contracts for you to implement (such as [reducers](../understanding/thinking-in-redux/Glossary.md#reducer)) and provides a few helper functions to tie these contracts together.

This section documents the complete Redux API. Keep in mind that Redux is only concerned with managing the state. In a real app, you'll also want to use UI bindings like [react-redux](https://github.com/gaearon/react-redux).
**In practice, you won't use the Redux core directly**. [**Redux Toolkit**](https://redux-toolkit.js.org) is our official recommended approach for writing Redux logic. It wraps around the Redux core, and contains packages and functions that we think are essential for building a Redux app. Redux Toolkit builds in our suggested best practices, simplifies most Redux tasks, prevents common mistakes, and makes it easier to write Redux applications. Additionally, [**React-Redux**](https://react-redux.js.org) lets your React components talk to the Redux store.

### Top-Level Exports
See their API docs here:

- [createStore(reducer, [preloadedState], [enhancer])](createStore.md)
- https://redux-toolkit.js.org/
- https://react-redux.js.org/

:::danger

**The original Redux core `createStore` method is deprecated!**

`createStore` will continue to work indefinitely, but we discourage direct use of `createStore` or the original `redux` package.

Instead, you should use [the `configureStore` method](https://redux-toolkit.js.org/api/configureStore) from our official [Redux Toolkit](https://redux-toolkit.js.org) package, which wraps `createStore` to provide a better default setup and configuration approach. You should also use Redux Toolkit's [`createSlice` method](https://redux-toolkit.js.org/api/createSlice) for writing reducer logic.

Redux Toolkit also re-exports all of the other APIs included in the `redux` package as well.

See the [**Migrating to Modern Redux** page](../usage/migrating-to-modern-redux.mdx) for details on how to update your existing legacy Redux codebase to use Redux Toolkit.

:::

## Top-Level Exports

- [createStore(reducer, preloadedState?, enhancer?)](createStore.md)
- [combineReducers(reducers)](combineReducers.md)
- [applyMiddleware(...middlewares)](applyMiddleware.md)
- [bindActionCreators(actionCreators, dispatch)](bindActionCreators.md)
- [compose(...functions)](compose.md)

### Store API
## Store API

- [Store](Store.md)
- [getState()](Store.md#getState)
- [dispatch(action)](Store.md#dispatchaction)
- [subscribe(listener)](Store.md#subscribelistener)
- [replaceReducer(nextReducer)](Store.md#replacereducernextreducer)

### Importing

Every function described above is a top-level export. You can import any of them like this:

#### ES6

```js
import { createStore } from 'redux'
```

#### ES5 (CommonJS)

```js
var createStore = require('redux').createStore
```

#### ES5 (UMD build)

```js
var createStore = Redux.createStore
```
18 changes: 14 additions & 4 deletions docs/api/applyMiddleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,32 @@ description: 'API > applyMiddleware: extending the Redux store'

# `applyMiddleware(...middleware)`

## Overview

Middleware is the suggested way to extend Redux with custom functionality. Middleware lets you wrap the store's [`dispatch`](Store.md#dispatchaction) 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.

:::warning Warning

You shouldn't have to call `applyMiddleware` directly. Redux Toolkit's [`configureStore` method](https://redux-toolkit.js.org/api/configureStore) automatically adds a default set of middleware to the store, or can accept a list of middleware to add.

:::

The most common use case for middleware is to support asynchronous actions without much boilerplate code or a dependency on a library like [Rx](https://github.com/Reactive-Extensions/RxJS). It does so by letting you dispatch [async actions](../understanding/thinking-in-redux/Glossary.md#async-action) in addition to normal actions.

For example, [redux-thunk](https://github.com/reduxjs/redux-thunk) lets the action creators invert control by dispatching functions. They would receive [`dispatch`](Store.md#dispatchaction) as an argument and may call it asynchronously. Such functions are called _thunks_. Another example of middleware is [redux-promise](https://github.com/acdlite/redux-promise). It lets you dispatch a [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) async action, and dispatches a normal action when the Promise resolves.

Middleware is not baked into [`createStore`](createStore.md) and is not a fundamental part of the Redux architecture, but we consider it useful enough to be supported right in the core. This way, there is a single standard way to extend [`dispatch`](Store.md#dispatchaction) in the ecosystem, and different middleware may compete in expressiveness and utility.
The original Redux [`createStore`](createStore.md) method does not understand what middleware are out of the box - it has to be configured with `applyMiddleware` to add that behavior. However, Redux Toolkit's [`configureStore` method](https://redux-toolkit.js.org/api/configureStore) automatically adds middleware support by default.

#### Arguments
## Arguments

- `...middleware` (_arguments_): Functions that conform to the Redux _middleware API_. Each middleware receives [`Store`](Store.md)'s [`dispatch`](Store.md#dispatchaction) and [`getState`](Store.md#getState) functions as named arguments, and returns a function. That function will be given the `next` middleware's dispatch method, and is expected to return a function of `action` calling `next(action)` with a potentially different argument, or at a different time, or maybe not calling it at all. The last middleware in the chain will receive the real store's [`dispatch`](Store.md#dispatchaction) method as the `next` parameter, thus ending the chain. So, the middleware signature is `({ getState, dispatch }) => next => action`.

#### Returns
### 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.

## Examples

#### Example: Custom Logger Middleware

```js
Expand Down Expand Up @@ -191,7 +201,7 @@ export default connect(state => ({
}))(SandwichShop)
```

#### Tips
## Tips

- Middleware only wraps the store's [`dispatch`](Store.md#dispatchaction) function. Technically, anything a middleware can do, you can do manually by wrapping every `dispatch` call, but it's easier to manage this in a single place and define action transformations on the scale of the whole project.

Expand Down
20 changes: 11 additions & 9 deletions docs/api/bindActionCreators.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ description: 'API > bindActionCreators: wrapping action creators for dispatching

# `bindActionCreators(actionCreators, dispatch)`

## Overview

Turns an object whose values are [action creators](../understanding/thinking-in-redux/Glossary.md#action-creator), into an object with the same keys, but with every action creator wrapped into a [`dispatch`](Store.md#dispatchaction) call so they may be invoked directly.

Normally you should just call [`dispatch`](Store.md#dispatchaction) directly on your [`Store`](Store.md) instance. If you use Redux with React, [react-redux](https://github.com/gaearon/react-redux) will provide you with the [`dispatch`](Store.md#dispatchaction) function so you can call it directly, too.
Expand All @@ -17,17 +19,23 @@ The only use case for `bindActionCreators` is when you want to pass some action

For convenience, you can also pass an action creator as the first argument, and get a dispatch wrapped function in return.

#### Parameters
:::warning Warning

This was originally intended for use with the legacy React-Redux `connect` method. It still works, but is rarely needed.

:::

## Parameters

1. `actionCreators` (_Function_ or _Object_): An [action creator](../understanding/thinking-in-redux/Glossary.md#action-creator), or an object whose values are action creators.

2. `dispatch` (_Function_): A [`dispatch`](Store.md#dispatchaction) function available on the [`Store`](Store.md) instance.

#### Returns
### Returns

(_Function_ or _Object_): An object mimicking the original object, but with each function immediately dispatching the action returned by the corresponding action creator. If you passed a function as `actionCreators`, the return value will also be a single function.

#### Example
## Example

#### `TodoActionCreators.js`

Expand Down Expand Up @@ -103,9 +111,3 @@ function TodoListContainer(props) {

export default connect(state => ({ todos: state.todos }))(TodoListContainer)
```

#### Tips

- 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` properties are functions. The module system doesn't matter.

0 comments on commit e124f0b

Please sign in to comment.