Skip to content

Add connect() API doc #1140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 23, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"semi": false,
"singleQuote": true
"singleQuote": true,
"tabWidth": 2
}
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@
- [Basic Tutorial](./introduction/basic-tutorial.md)
- Using React Redux
- [Connect: Extracting Data with `mapStateToProps`](./using-react-redux/connect-extracting-data-with-mapStateToProps.md)
- [API](api.md#api)
- [`<Provider store>`](api.md#provider-store)
- [`connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])`](api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)
- [`connectAdvanced(selectorFactory, [connectOptions])`](api.md#connectadvancedselectorfactory-connectoptions)
- API
- [`<Provider store>`](./api/Provider.md)
- [`connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])`](./api/connect.md)
- [`connectAdvanced(selectorFactory, [connectOptions])`](./api/connect-advanced.md)
- [Troubleshooting](troubleshooting.md#troubleshooting)
491 changes: 0 additions & 491 deletions docs/api.md

This file was deleted.

79 changes: 39 additions & 40 deletions docs/api/Provider.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
id: provider
title: Provider
sidebar_label: Provider
hide_title: true
---

# `<Provider />`
@@ -18,62 +19,60 @@ Note: If you really need to, you can manually pass `store` as a prop to a connec

### Props

`store` (Redux Store)
`store` ([Redux Store](https://redux.js.org/api/store))
The single Redux `store` in your application.

`children` (ReactElement)
The root of your component hierarchy.


### Example Usage

In the example below, the `<App />` component is our root-level component. This means it’s at the very top of our component hierarchy.

**Vanilla React Example**

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import { App } from './App';
import createStore from './createReduxStore';
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'

const store = createStore();
import { App } from './App'
import createStore from './createReduxStore'

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
```
const store = createStore()

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
```

**Usage with React Router**

```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router, Route } from 'react-router-dom';

import { App } from './App';
import { Foo } from './Foo';
import { Bar } from './Bar';
import createStore from './createReduxStore';

const store = createStore();

ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<Route path="foo" component={Foo}/>
<Route path="bar" component={Bar}/>
</Route>
</Router>
</Provider>,
document.getElementById('root')
)
```
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { Router, Route } from 'react-router-dom'

import { App } from './App'
import { Foo } from './Foo'
import { Bar } from './Bar'
import createStore from './createReduxStore'

const store = createStore()

ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<Route path="foo" component={Foo} />
<Route path="bar" component={Bar} />
</Route>
</Router>
</Provider>,
document.getElementById('root')
)
```
86 changes: 86 additions & 0 deletions docs/api/connect-advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
id: connect-advanced
title: connectAdvanced
sidebar_label: connectAdvanced()
hide_title: true
---

# `connectAdvanced()`

```js
connectAdvanced(selectorFactory, connectOptions?)
```
Connects a React component to a Redux store. It is the base for `connect()` but is less opinionated about how to combine `state`, `props`, and `dispatch` into your final props. It makes no assumptions about defaults or memoization of results, leaving those responsibilities to the caller.
It does not modify the component class passed to it; instead, it _returns_ a new, connected component class for you to use.
Most applications will not need to use this, as the default behavior in `connect` is intended to work for most use cases.
> Note: `connectAdvanced` was added in version 5.0, and `connect` was reimplemented as a specific set of parameters to `connectAdvanced`.
## Arguments
- `selectorFactory(dispatch, factoryOptions): selector(state, ownProps): props` \(_Function_): Initializes a selector function (during each instance's constructor). That selector function is called any time the connector component needs to compute new props, as a result of a store state change or receiving new props. The result of `selector` is expected to be a plain object, which is passed as the props to the wrapped component. If a consecutive call to `selector` returns the same object (`===`) as its previous call, the component will not be re-rendered. It's the responsibility of `selector` to return that previous object when appropriate.
- [`connectOptions`] _(Object)_ If specified, further customizes the behavior of the connector.
- [`getDisplayName`] _(Function)_: computes the connector component's displayName property relative to that of the wrapped component. Usually overridden by wrapper functions. Default value: `name => 'ConnectAdvanced('+name+')'`
- [`methodName`] _(String)_: shown in error messages. Usually overridden by wrapper functions. Default value: `'connectAdvanced'`
- [`renderCountProp`] _(String)_: if defined, a property named this value will be added to the props passed to the wrapped component. Its value will be the number of times the component has been rendered, which can be useful for tracking down unnecessary re-renders. Default value: `undefined`
- [`shouldHandleStateChanges`] _(Boolean)_: controls whether the connector component subscribes to redux store state changes. If set to false, it will only re-render when parent component re-renders. Default value: `true`
- [`forwardRef`] _(Boolean)_: If true, adding a ref to the connected wrapper component will actually return the instance of the wrapped component.
- Additionally, any extra options passed via `connectOptions` will be passed through to your `selectorFactory` in the `factoryOptions` argument.
<a id="connectAdvanced-returns"></a>
## Returns
A higher-order React component class that builds props from the store state and passes them to the wrapped component. A higher-order component is a function which accepts a component argument and returns a new component.
### Static Properties
- `WrappedComponent` _(Component)_: The original component class passed to `connectAdvanced(...)(Component)`.
### Static Methods
All the original static methods of the component are hoisted.
## Remarks
- Since `connectAdvanced` returns a higher-order component, it needs to be invoked two times. The first time with its arguments as described above, and a second time, with the component: `connectAdvanced(selectorFactory)(MyComponent)`.
- `connectAdvanced` does not modify the passed React component. It returns a new, connected component, that you should use instead.
<a id="connectAdvanced-examples"></a>
### Examples
### Inject `todos` of a specific user depending on props, and inject `props.userId` into the action
```js
import * as actionCreators from './actionCreators'
import { bindActionCreators } from 'redux'

function selectorFactory(dispatch) {
let ownProps = {}
let result = {}

const actions = bindActionCreators(actionCreators, dispatch)
const addTodo = text => actions.addTodo(ownProps.userId, text)

return (nextState, nextOwnProps) => {
const todos = nextState.todos[nextOwnProps.userId]
const nextResult = { ...nextOwnProps, todos, addTodo }
ownProps = nextOwnProps
if (!shallowEqual(result, nextResult)) result = nextResult
return result
}
}
export default connectAdvanced(selectorFactory)(TodoApp)
```
628 changes: 628 additions & 0 deletions docs/api/connect.md

Large diffs are not rendered by default.

100 changes: 50 additions & 50 deletions docs/introduction/basic-tutorial.md
Original file line number Diff line number Diff line change
@@ -74,20 +74,20 @@ First we need to make the `store` available to our app. To do this, we wrap our

```jsx
// index.js
import React from "react";
import ReactDOM from "react-dom";
import TodoApp from "./TodoApp";
import React from 'react'
import ReactDOM from 'react-dom'
import TodoApp from './TodoApp'

import { Provider } from "react-redux";
import store from "./redux/store";
import { Provider } from 'react-redux'
import store from './redux/store'

const rootElement = document.getElementById("root");
const rootElement = document.getElementById('root')
ReactDOM.render(
<Provider store={store}>
<TodoApp />
</Provider>,
rootElement
);
)
```

Notice how our `<TodoApp />` is now wrapped with the `<Provider />` with `store` passed in as a prop.
@@ -96,7 +96,7 @@ Notice how our `<TodoApp />` is now wrapped with the `<Provider />` with `store`

### Connecting the Components

React Redux provides a `connect` function for you to read values from the Redux store (and re-read the values when the store updates).
React Redux provides a `connect` function for you to read values from the Redux store (and re-read the values when the store updates).

The `connect` function takes two arguments, both optional:

@@ -111,25 +111,25 @@ Normally, you’ll call `connect` in this way:
```js
const mapStateToProps = (state, ownProps) => ({
// ... computed data from state and optionally ownProps
});
})

const mapDispatchToProps = {
// ... normally is an object full of action creators
};
}

// `connect` returns a new function that accepts the component to wrap:
const connectToStore = connect(
mapStateToProps,
mapDispatchToProps
);
)
// and that function returns the connected, wrapper component:
const ConnectedComponent = connectToStore(Component);
const ConnectedComponent = connectToStore(Component)

// We normally do both in one step, like this:
connect(
mapStateToProps,
mapDispatchToProps
)(Component);
)(Component)
```

Let’s work on `<AddTodo />` first. It needs to trigger changes to the `store` to add new todos. Therefore, it needs to be able to `dispatch` actions to the store. Here’s how we do it.
@@ -138,16 +138,16 @@ Our `addTodo` action creator looks like this:

```js
// redux/actions.js
import { ADD_TODO } from "./actionTypes";
import { ADD_TODO } from './actionTypes'

let nextTodoId = 0;
let nextTodoId = 0
export const addTodo = content => ({
type: ADD_TODO,
payload: {
id: ++nextTodoId,
content
}
});
})

// ... other actions
```
@@ -158,8 +158,8 @@ By passing it to `connect`, our component receives it as a prop, and it will aut
// components/AddTodo.js

// ... other imports
import { connect } from "react-redux";
import { addTodo } from "../redux/actions";
import { connect } from 'react-redux'
import { addTodo } from '../redux/actions'

class AddTodo extends React.Component {
// ... component implementation
@@ -168,7 +168,7 @@ class AddTodo extends React.Component {
export default connect(
null,
{ addTodo }
)(AddTodo);
)(AddTodo)
```

Notice now that `<AddTodo />` is wrapped with a parent component called `<Connect(AddTodo) />`. Meanwhile, `<AddTodo />` now gains one prop: the `addTodo` action.
@@ -180,20 +180,20 @@ We also need to implement the `handleAddTodo` function to let it dispatch the `a
```jsx
// components/AddTodo.js

import React from "react";
import { connect } from "react-redux";
import { addTodo } from "../redux/actions";
import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../redux/actions'

class AddTodo extends React.Component {
// ...

handleAddTodo = () => {
// dispatches actions to add todo
this.props.addTodo(this.state.input);
this.props.addTodo(this.state.input)

// sets state back to empty string
this.setState({ input: "" });
};
this.setState({ input: '' })
}

render() {
return (
@@ -206,14 +206,14 @@ class AddTodo extends React.Component {
Add Todo
</button>
</div>
);
)
}
}

export default connect(
null,
{ addTodo }
)(AddTodo);
)(AddTodo)
```

Now our `<AddTodo />` is connected to the store. When we add a todo it would dispatch an action to change the store. We are not seeing it in the app because the other components are not connected yet. If you have the Redux DevTools Extension hooked up, you should see the action being dispatched:
@@ -253,16 +253,16 @@ Luckily we have a selector that does exactly this. We may simply import the sele
```js
// redux/selectors.js

export const getTodosState = store => store.todos;
export const getTodosState = store => store.todos

export const getTodoList = store =>
getTodosState(store) ? getTodosState(store).allIds : [];
getTodosState(store) ? getTodosState(store).allIds : []

export const getTodoById = (store, id) =>
getTodosState(store) ? { ...getTodosState(store).byIds[id], id } : {};
getTodosState(store) ? { ...getTodosState(store).byIds[id], id } : {}

export const getTodos = store =>
getTodoList(store).map(id => getTodoById(store, id));
getTodoList(store).map(id => getTodoById(store, id))
```

```js
@@ -303,7 +303,7 @@ If you call `connect` without providing any arguments, your component will:

```js
// ... Component
export default connect()(Component); // Component will receive `dispatch` (just like our <TodoList />!)
export default connect()(Component) // Component will receive `dispatch` (just like our <TodoList />!)
```

#### Subscribe to the store and do not inject action creators
@@ -315,8 +315,8 @@ If you call `connect` with only `mapStateToProps`, your component will:

```js
// ... Component
const mapStateToProps = state => state.partOfState;
export default connect(mapStateToProps)(Component);
const mapStateToProps = state => state.partOfState
export default connect(mapStateToProps)(Component)
```

#### Do not subscribe to the store and inject action creators
@@ -327,12 +327,12 @@ If you call `connect` with only `mapDispatchToProps`, your component will:
- receive each of the action creators you inject with `mapDispatchToProps` as props and automatically dispatch the actions upon being called

```js
import { addTodo } from "./actionCreators";
import { addTodo } from './actionCreators'
// ... Component
export default connect(
null,
{ addTodo }
)(Component);
)(Component)
```

#### Subscribe to the store and inject action creators
@@ -343,16 +343,16 @@ If you call `connect` with both `mapStateToProps` and `mapDispatchToProps`, your
- receive all of the action creators you inject with `mapDispatchToProps` as props and automatically dispatch the actions upon being called.

```js
import * as actionCreators from "./actionCreators";
import * as actionCreators from './actionCreators'
// ... Component
const mapStateToProps = state => state.partOfState;
const mapStateToProps = state => state.partOfState
export default connect(
mapStateToProps,
actionCreators
)(Component);
)(Component)
```

These four cases cover the most basic usages of `connect`. To read more about `connect`, continue reading our [API section](./api.md) that explains it in more detail.
These four cases cover the most basic usages of `connect`. To read more about `connect`, continue reading our [API section](../api/connect.md) that explains it in more detail.

<!-- TODO: Put up link to the page that further explains connect -->

@@ -410,17 +410,17 @@ Meanwhile, we also need to update our `<TodoList />` component to filter todos a

// ... other selectors
export const getTodosByVisibilityFilter = (store, visibilityFilter) => {
const allTodos = getTodos(store);
const allTodos = getTodos(store)
switch (visibilityFilter) {
case VISIBILITY_FILTERS.COMPLETED:
return allTodos.filter(todo => todo.completed);
return allTodos.filter(todo => todo.completed)
case VISIBILITY_FILTERS.INCOMPLETE:
return allTodos.filter(todo => !todo.completed);
return allTodos.filter(todo => !todo.completed)
case VISIBILITY_FILTERS.ALL:
default:
return allTodos;
return allTodos
}
};
}
```

And connecting to the store with the help of the selector:
@@ -431,12 +431,12 @@ And connecting to the store with the help of the selector:
// ...

const mapStateToProps = state => {
const { visibilityFilter } = state;
const todos = getTodosByVisibilityFilter(state, visibilityFilter);
return { todos };
};
const { visibilityFilter } = state
const todos = getTodosByVisibilityFilter(state, visibilityFilter)
return { todos }
}

export default connect(mapStateToProps)(TodoList);
export default connect(mapStateToProps)(TodoList)
```

Now we've finished a very simple example of a todo app with React Redux. All our components are connected! Isn't that nice? 🎉🎊
26 changes: 13 additions & 13 deletions docs/introduction/quick-start.md
Original file line number Diff line number Diff line change
@@ -32,45 +32,45 @@ You'll also need to [install Redux](https://redux-docs.netlify.com/introduction/
React Redux provides `<Provider />`, which makes the Redux store available to the rest of your app:

```js
import React from "react";
import ReactDOM from "react-dom";
import React from 'react'
import ReactDOM from 'react-dom'

import { Provider } from "react-redux";
import store from "./store";
import { Provider } from 'react-redux'
import store from './store'

import App from "./App";
import App from './App'

const rootElement = document.getElementById("root");
const rootElement = document.getElementById('root')
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
)
```

React Redux provides a `connect` function for you to connect your component to the store.

Normally, you’ll call `connect` in this way:

```js
import { connect } from "react-redux";
import { increment, decrement, reset } from "./actionCreators";
import { connect } from 'react-redux'
import { increment, decrement, reset } from './actionCreators'

// const Counter = ...

const mapStateToProps = (state /*, ownProps*/) => {
return {
counter: state.counter
};
};
}
}

const mapDispatchToProps = { increment, decrement, reset };
const mapDispatchToProps = { increment, decrement, reset }

export default connect(
mapStateToProps,
mapDispatchToProps
)(Counter);
)(Counter)
```

## Help and Discussion
49 changes: 20 additions & 29 deletions docs/introduction/why-use-react-redux.md
Original file line number Diff line number Diff line change
@@ -7,11 +7,11 @@ sidebar_label: Why Use React Redux?

# Why 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.
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.
**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.

To understand why you should use React Redux, it may help to understand what a "UI binding library" does.

@@ -22,77 +22,68 @@ To understand why you should use React Redux, it may help to understand what a "
> - [You Might Not Need Redux](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367)
> - [Idiomatic Redux: The Tao of Redux, Part 1 - Implementation and Intent](https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-1/)

## Integrating Redux with a UI

Using Redux with _any_ UI layer requires [the same consistent set of steps](https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/ui-layer.html#/4):

1. Create a Redux store
2. Subscribe to updates
3. Inside the subscription callback:
1. Get the current store state
2. Extract the data needed by this piece of UI
3. Update the UI with the data
1. Get the current store state
2. Extract the data needed by this piece of UI
3. Update the UI with the data
4. If necessary, render the UI with initial state
5. Respond to UI inputs by dispatching Redux actions

While it is possible to write this logic by hand, doing so would become very repetitive. In addition, optimizing UI performance would require complicated logic.
While it is possible to write this 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.**
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.**

> **Note**: For a deeper look at how React Redux works internally and how it handles the store interaction for you, see **[Idiomatic Redux: The History and Implementation of React Redux](https://blog.isquaredsoftware.com/2018/11/react-redux-history-implementation/)**.

## Reasons to Use React Redux

### It is the Official Redux UI Bindings for React

While Redux can be used with any UI layer, it was originally designed and intended for use with React. There are [UI binding layers for many other frameworks](https://redux.js.org/introduction/ecosystem#library-integration-and-bindings), but React Redux is maintained directly by the Redux team.

As the offical Redux binding for React, React Redux is kept up-to-date with any API changes from either library, to ensure that your React components behave as expected. Its intended usage adopts the design principles of React - writing declarative components.
While Redux can be used with any UI layer, it was originally designed and intended for use with React. There are [UI binding layers for many other frameworks](https://redux.js.org/introduction/ecosystem#library-integration-and-bindings), but React Redux is maintained directly by the Redux team.

As the offical Redux binding for React, React Redux is kept up-to-date with any API changes from either library, to ensure that your React components behave as expected. Its intended usage adopts the design principles of React - writing declarative components.

### It Encourages Good React Architecture

React components are a lot like functions. While it's possible to write all your code in a single function, it's usually better to split that logic into smaller functions that each handle a specific task, making them easier to understand.
React components are a lot like functions. While it's possible to write all your code in a single function, it's usually better to split that logic into smaller functions that each handle a specific task, making them easier to understand.

Similarly, while you can write large React components that handle many different tasks, it's usually better to split up components based on responsibilities. In particular, it is common to have "container" components that are responsible for collecting and managing some kind of data, and "presentational" components that simply display UI based on whatever data they've received as props.
Similarly, while you can write large React components that handle many different tasks, it's usually better to split up components based on responsibilities. In particular, it is common to have "container" components that are responsible for collecting and managing some kind of data, and "presentational" components that simply display UI based on whatever data they've received as props.

**The React Redux `connect` function generates "container" wrapper components that handle the process of interacting with the store for you**. That way, your own components can focus on other tasks, whether it be collecting other data, or just displaying a piece of the UI. In addition, **`connect` abstracts away the question of _which_ store is being used, making your own components more reusable**.

As a general architectural principle, **we want to keep our own components "unaware" of Redux**. They should simply receive data and functions as props, just like any other React component. This ultimately makes it easier to test and reuse your own components.
**The React Redux `connect` function generates "container" wrapper components that handle the process of interacting with the store for you**. That way, your own components can focus on other tasks, whether it be collecting other data, or just displaying a piece of the UI. In addition, **`connect` abstracts away the question of _which_ store is being used, making your own components more reusable**.

As a general architectural principle, **we want to keep our own components "unaware" of Redux**. They should simply receive data and functions as props, just like any other React component. This ultimately makes it easier to test and reuse your own components.

### It Implements Performance Optimizations For You

React is generally fast, but by default any updates to a component will cause React to re-render all of the components inside that part of the component tree. This does require work, and if the data for a given component hasn't changed, then re-rendering is likely some wasted effort because the requested UI output would be the same.

If performance is a concern, the best way to improve performance is to skip unnecessary re-renders, so that components only re-render when their data has actually changed. **React Redux implements many performance optimizations internally, so that your own component only re-renders when it actually needs to.**
React is generally fast, but by default any updates to a component will cause React to re-render all of the components inside that part of the component tree. This does require work, and if the data for a given component hasn't changed, then re-rendering is likely some wasted effort because the requested UI output would be the same.

In addition, by connecting multiple components in your React component tree, you can ensure that each connected component only extracts the specific pieces of data from the store state that are needed by that component. This means that your own component will need to re-render less often, because most of the time those specific pieces of data haven't changed.
If performance is a concern, the best way to improve performance is to skip unnecessary re-renders, so that components only re-render when their data has actually changed. **React Redux implements many performance optimizations internally, so that your own component only re-renders when it actually needs to.**

In addition, by connecting multiple components in your React component tree, you can ensure that each connected component only extracts the specific pieces of data from the store state that are needed by that component. This means that your own component will need to re-render less often, because most of the time those specific pieces of data haven't changed.

### Community Support

As the official binding library for React and Redux, React Redux has a large community of users. This makes it easier to ask for help, learn about best practices, use libraries that build on top of React Redux, and reuse your knowledge across different applications.


As the official binding library for React and Redux, React Redux has a large community of users. This makes it easier to ask for help, learn about best practices, use libraries that build on top of React Redux, and reuse your knowledge across different applications.

## Links and References


### Understanding React Redux

- [Idiomatic Redux: The History and Implementation of React Redux](https://blog.isquaredsoftware.com/2018/11/react-redux-history-implementation/)
- [`connect.js` Explained](https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e)
- [Redux Fundamentals workshop slides](https://blog.isquaredsoftware.com/2018/06/redux-fundamentals-workshop-slides/)
- [UI Layer Integration](https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/ui-layer.html)
- [Using React Redux](https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/react-redux.html)

- [UI Layer Integration](https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/ui-layer.html)
- [Using React Redux](https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/react-redux.html)

### Community Resources

- Discord channel: [#redux on Reactiflux](https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e) ([Reactiflux invite link](https://reactiflux.com))
- Discord channel: [#redux on Reactiflux](https://gist.github.com/gaearon/1d19088790e70ac32ea636c025ba424e) ([Reactiflux invite link](https://reactiflux.com))
- Stack Overflow topics: [Redux](https://stackoverflow.com/questions/tagged/redux), [React Redux](https://stackoverflow.com/questions/tagged/redux)
- Reddit: [/r/reactjs](https://www.reddit.com/r/reactjs/), [/r/reduxjs](https://www.reddit.com/r/reduxjs/)
- Github issues (bug reports and feature requests): https://github.com/reduxjs/react-redux/issues
23 changes: 15 additions & 8 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@ hide_title: true
Make sure to check out [Troubleshooting Redux](http://redux.js.org/docs/Troubleshooting.html) first.

### I'm getting the following alert: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
This warning is shown when using react 15.5.*. Basically, now it's just a warning, but in react16 the application might break. the PropTypes should now be imported from 'prop-types' package, and not from the react package.

This warning is shown when using react 15.5.\*. Basically, now it's just a warning, but in react16 the application might break. the PropTypes should now be imported from 'prop-types' package, and not from the react package.

Update to the latest version of react-redux.

@@ -19,8 +20,8 @@ Update to the latest version of react-redux.
See the link above.
In short,

* Reducers should never mutate state, they must return new objects, or React Redux won’t see the updates.
* Make sure you either bind action creators with the `mapDispatchToProps` argument to `connect()` or with the `bindActionCreators()` method, or that you manually call `dispatch()`. Just calling your `MyActionCreators.addTodo()` function won’t work because it just *returns* an action, but does not *dispatch* it.
- Reducers should never mutate state, they must return new objects, or React Redux won’t see the updates.
- Make sure you either bind action creators with the `mapDispatchToProps` argument to `connect()` or with the `bindActionCreators()` method, or that you manually call `dispatch()`. Just calling your `MyActionCreators.addTodo()` function won’t work because it just _returns_ an action, but does not _dispatch_ it.

### My views aren’t updating on route change with React Router 0.13

@@ -29,7 +30,8 @@ If you’re using React Router 0.13, you might [bump into this problem](https://
Root view:

```jsx
Router.run(routes, Router.HistoryLocation, (Handler, routerState) => { // note "routerState" here
Router.run(routes, Router.HistoryLocation, (Handler, routerState) => {
// note "routerState" here
ReactDOM.render(
<Provider store={store}>
{/* note "routerState" here */}
@@ -56,7 +58,7 @@ You can also upgrade to React Router 1.0 which shouldn’t have this problem. (L

If your views depend on global state or [React “context”](http://facebook.github.io/react/docs/context.html), you might find that views decorated with `connect()` will fail to update.

>This is because `connect()` implements [shouldComponentUpdate](https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) by default, assuming that your component will produce the same results given the same props and state. This is a similar concept to React’s [PureRenderMixin](https://facebook.github.io/react/docs/pure-render-mixin.html).
> This is because `connect()` implements [shouldComponentUpdate](https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) by default, assuming that your component will produce the same results given the same props and state. This is a similar concept to React’s [PureRenderMixin](https://facebook.github.io/react/docs/pure-render-mixin.html).
The _best_ solution to this is to make sure that your components are pure and pass any external state to them via props. This will ensure that your views do not re-render unless they actually need to re-render and will greatly speed up your application.

@@ -67,9 +69,14 @@ function mapStateToProps(state) {
return { todos: state.todos }
}

export default connect(mapStateToProps, null, null, {
pure: false
})(TodoApp)
export default connect(
mapStateToProps,
null,
null,
{
pure: false
}
)(TodoApp)
```

This will remove the assumption that `TodoApp` is pure and cause it to update whenever its parent component renders. Note that this will make your application less performant, so only do this if you have no other option.
Original file line number Diff line number Diff line change
@@ -27,15 +27,15 @@ The `mapDispatchToProps` functions are normally referred to as `mapDispatch` for
If you don't specify the second argument to `connect()`, your component will receive `dispatch` by default. For example:

```js
connect()(MyComponent);
connect()(MyComponent)
// which is equivalent with
connect(
null,
null
)(MyComponent);
)(MyComponent)

// or
connect(mapStateToProps /** no second argument */)(MyComponent);
connect(mapStateToProps /** no second argument */)(MyComponent)
```

Once you have connected your component in this way, your component receives `props.dispatch`. You may use it to dispatch actions to the store.
@@ -44,12 +44,12 @@ Once you have connected your component in this way, your component receives `pro
function Counter({ count, dispatch }) {
return (
<div>
<button onClick={() => dispatch({ type: "DECREMENT" })}>-</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
<span>{count}</span>
<button onClick={() => dispatch({ type: "INCREMENT" })}>+</button>
<button onClick={() => dispatch({ type: "RESET" })}>reset</button>
<button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
<button onClick={() => dispatch({ type: 'RESET' })}>reset</button>
</div>
);
)
}
```

@@ -89,7 +89,7 @@ const TodoList = ({ todos, toggleTodo }) => (
<Todo todo={todo} onClick={toggleTodo} />
))}
</div>
);
)
```

This is what React Redux’s `connect` does — it encapsulates the logic of talking to the Redux store and lets you not worry about it. And this is what you should totally make full use of in your implementation.
@@ -123,11 +123,11 @@ You will normally make use of this by returning new functions that call `dispatc
const mapDispatchToProps = dispatch => {
return {
// dispatching plain actions
increment: () => dispatch({ type: "INCREMENT" }),
decrement: () => dispatch({ type: "DECREMENT" }),
reset: () => dispatch({ type: "RESET" })
};
};
increment: () => dispatch({ type: 'INCREMENT' }),
decrement: () => dispatch({ type: 'DECREMENT' }),
reset: () => dispatch({ type: 'RESET' })
}
}
```

You will also likely want to forward arguments to your action creators:
@@ -141,8 +141,8 @@ const mapDispatchToProps = dispatch => {
// implicitly forwarding arguments
onReceiveImpressions: (...impressions) =>
dispatch(trackImpressions(impressions))
};
};
}
}
```

**`ownProps` ( optional )**
@@ -153,12 +153,12 @@ This means, instead of re-binding new `props` to action dispatchers upon compone

```js
// binds on component re-rendering
<button onClick={() => this.props.toggleTodo(this.props.todoId)} />;
;<button onClick={() => this.props.toggleTodo(this.props.todoId)} />

// binds on `props` change
const mapDispatchToProps = (dispatch, ownProps) => {
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId));
};
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId))
}
```

### Return
@@ -169,18 +169,18 @@ Your `mapDispatchToProps` function should return a plain object:
- If you use action creators ( as oppose to plain object actions ) inside `dispatch`, it is a convention to simply name the field key the same name as the action creator:

```js
const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const reset = () => ({ type: "RESET" });
const increment = () => ({ type: 'INCREMENT' })
const decrement = () => ({ type: 'DECREMENT' })
const reset = () => ({ type: 'RESET' })

const mapDispatchToProps = dispatch => {
return {
// dispatching actions returned by action creators
increment: () => dispatch(increment()),
decrement: () => dispatch(decrement()),
reset: () => dispatch(reset())
};
};
}
}
```

The return of the `mapDispatchToProps` function will be merged to your connected component as props. You may call them directly to dispatch its action.
@@ -194,7 +194,7 @@ function Counter({ count, increment, decrement, reset }) {
<button onClick={increment}>+</button>
<button onClick={reset}>reset</button>
</div>
);
)
}
```

@@ -214,18 +214,21 @@ Wrapping these functions by hand is tedious, so Redux provides a function to sim
The wrapper functions generated by `bindActionCreators` will automatically forward all of their arguments, so you don't need to do that by hand.

```js
import { bindActionCreators } from "redux";
import { bindActionCreators } from 'redux'

const increment = () => ({ type: "INCREMENT" });
const decrement = () => ({ type: "DECREMENT" });
const reset = () => ({ type: "RESET" });
const increment = () => ({ type: 'INCREMENT' })
const decrement = () => ({ type: 'DECREMENT' })
const reset = () => ({ type: 'RESET' })

// binding an action creator
// returns (...args) => dispatch(increment(...args))
const boundIncrement = bindActionCreators(increment, dispatch);
const boundIncrement = bindActionCreators(increment, dispatch)

// binding an object full of action creators
const boundActionCreators = bindActionCreators({ increment, decrement, reset }, dispatch);
const boundActionCreators = bindActionCreators(
{ increment, decrement, reset },
dispatch
)
// returns
// {
// increment: (...args) => dispatch(increment(...args)),
@@ -237,33 +240,33 @@ const boundActionCreators = bindActionCreators({ increment, decrement, reset },
To use `bindActionCreators` in our `mapDispatchToProps` function:

```js
import { bindActionCreators } from "redux";
import { bindActionCreators } from 'redux'
// ...

function mapDispatchToProps(dispatch) {
return bindActionCreators({ increment, decrement, reset }, dispatch);
return bindActionCreators({ increment, decrement, reset }, dispatch)
}

// component receives props.increment, props.decrement, props.reset
connect(
null,
mapDispatchToProps
)(Counter);
)(Counter)
```

### Manually Injecting `dispatch`

If the `mapDispatchToProps` argument is supplied, the component will no longer receive the default `dispatch`. You may bring it back by adding it manually to the return of your `mapDispatchToProps`, although most of the time you shouldn’t need to do this:

```js
import { bindActionCreators } from "redux";
import { bindActionCreators } from 'redux'
// ...

function mapDispatchToProps(dispatch) {
return {
dispatch,
...bindActionCreators({ increment, decrement, reset }, dispatch)
};
}
}
```

@@ -282,7 +285,7 @@ Note that:

```js
// React Redux does this for you automatically:
dispatch => bindActionCreators(mapDispatchToProps, dispatch);
dispatch => bindActionCreators(mapDispatchToProps, dispatch)
```

Therefore, our `mapDispatchToProps` can simply be:
@@ -292,7 +295,7 @@ const mapDispatchToProps = {
increment,
decrement,
reset
};
}
```

Since the actual name of the variable is up to you, you might want to give it a name like `actionCreators`, or even define the object inline in the call to `connect`:
@@ -337,7 +340,7 @@ In another words, if you do:

```js
// component receives `dispatch`
connect(mapStateToProps /** no second argument*/)(Component);
connect(mapStateToProps /** no second argument*/)(Component)
```

**2. Your customized `mapDispatchToProps` function return specifically contains `dispatch`**
@@ -351,20 +354,20 @@ const mapDispatchToProps = dispatch => {
decrement: () => dispatch(decrement()),
reset: () => dispatch(reset()),
dispatch
};
};
}
}
```

Or alternatively, with `bindActionCreators`:

```js
import { bindActionCreators } from "redux";
import { bindActionCreators } from 'redux'

function mapDispatchToProps(dispatch) {
return {
dispatch,
...bindActionCreators({ increment, decrement, reset }, dispatch)
};
}
}
```

@@ -380,7 +383,7 @@ Yes. You can skip the first parameter by passing `undefined` or `null`. Your com
connect(
null,
mapDispatchToProps
)(MyComponent);
)(MyComponent)
```

### Can I call `store.dispatch`?
108 changes: 44 additions & 64 deletions docs/using-react-redux/connect-extracting-data-with-mapStateToProps.md

Large diffs are not rendered by default.

28 changes: 21 additions & 7 deletions package-lock.json
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
"build:umd:min": "cross-env NODE_ENV=production rollup -c -o dist/react-redux.min.js",
"build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min",
"clean": "rimraf lib dist es coverage",
"format": "prettier --write '{src,test}/**/*.js'",
"format": "prettier --write \"{src,test}/**/*.{js,ts}\" index.d.ts \"docs/**/*.md\"",
"lint": "eslint src test/utils test/components",
"prepare": "npm run clean && npm run build",
"pretest": "npm run lint",
2 changes: 1 addition & 1 deletion website/core/Footer.js
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ class Footer extends React.Component {
>
Using React Redux
</a>
<a href={this.docUrl("api")}>API Reference</a>
<a href={this.docUrl("api/connect")}>API Reference</a>
<a href={this.docUrl("troubleshooting")}>Guides</a>
</div>
<div>
5 changes: 3 additions & 2 deletions website/sidebars.json
Original file line number Diff line number Diff line change
@@ -10,8 +10,9 @@
"using-react-redux/connect-mapdispatch"
],
"API Reference": [
"api",
"api/provider"
"api/connect",
"api/provider",
"api/connect-advanced"
],
"Guides": [
"troubleshooting"
2 changes: 1 addition & 1 deletion website/siteConfig.js
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ const siteConfig = {
headerLinks: [
{ doc: "introduction/quick-start", label: "Quick Start" },
{ doc: "using-react-redux/connect-mapstate", label: "Using React Redux"},
{ doc: "api", label: "API" },
{ doc: "api/connect", label: "API" },
{ href : "https://www.github.com/reduxjs/react-redux", label : "Github"},
{ href: "/introduction/quick-start#help-and-discussion", label: "Need help?" },
],