Skip to content

Commit

Permalink
Merge branch 'master' into fix-layout-effect-race-condition
Browse files Browse the repository at this point in the history
  • Loading branch information
timdorr authored Apr 17, 2020
2 parents 58a964c + 79f3d13 commit ee80685
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 16 deletions.
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,30 @@ Performant and flexible.

## Installation

React Redux requires **React 16.8.3 or later.**
### Using Create React App

The recommended way to start new apps with React Redux is by using the [official Redux+JS template](https://github.com/reduxjs/cra-template-redux) for [Create React App](https://github.com/facebook/create-react-app), which takes advantage of [Redux Toolkit](https://redux-toolkit.js.org/).

```sh
npx create-react-app my-app --template redux
```
npm install --save react-redux

### An Existing React App

React Redux 7.1 requires **React 16.8.3 or later.**

To use React Redux with your React app, install it as a dependency:

```bash
# If you use npm:
npm install react-redux

# Or if you use Yarn:
yarn add react-redux
```

You'll also need to [install Redux](https://redux.js.org/introduction/installation) and [set up a Redux store](https://redux.js.org/recipes/configuring-your-store/) in your app.

This assumes that you’re using [npm](http://npmjs.com/) package manager
with a module bundler like [Webpack](https://webpack.js.org/) or
[Browserify](http://browserify.org/) to consume [CommonJS
Expand Down
4 changes: 2 additions & 2 deletions docs/api/connect.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ The second parameter is normally referred to as `ownProps` by convention.
<button onClick={() => this.props.toggleTodo(this.props.todoId)} />

// binds on `props` change
const mapDispatchToProps = (dispatch, ownProps) => {
const mapDispatchToProps = (dispatch, ownProps) => ({
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId))
}
})
```
The number of declared function parameters of `mapDispatchToProps` determines whether they receive ownProps. See notes [here](#the-arity-of-maptoprops-functions).
Expand Down
2 changes: 1 addition & 1 deletion docs/introduction/basic-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ const TodoList = // ... UI component implementation
export default connect(state => ({ todos: getTodos(state) }))(TodoList);
```

We recommend encapsulating any complex lookups or computations of data in selector functions. In addition, you can further optimize the performance by using [Reselect](https://github.com/reduxjs/reselect) to write “memoized” selectors that can skip unnecessary work. (See [the Redux docs page on Computing Derived Data](https://redux.js.org/recipes/computingderiveddata#sharing-selectors-across-multiple-components) and the blog post [Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance](https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/) for more information on why and how to use selector functions.)
We recommend encapsulating any complex lookups or computations of data in selector functions. In addition, you can further optimize the performance by using [Reselect](https://github.com/reduxjs/reselect) to write “memoized” selectors that can skip unnecessary work. (See [the Redux docs page on Computing Derived Data](https://redux.js.org/recipes/computing-derived-data#sharing-selectors-across-multiple-components) and the blog post [Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance](https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/) for more information on why and how to use selector functions.)

Now that our `<TodoList />` is connected to the store. It should receive the list of todos, map over them, and pass each todo to the `<Todo />` component. `<Todo />` will in turn render them to the screen. Now try adding a todo. It should come up on our todo list!

Expand Down
16 changes: 12 additions & 4 deletions docs/introduction/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@ sidebar_label: Quick Start

React Redux 7.1 requires **React 16.8.3 or later.**

To use React Redux with your React app:
### Using Create React App

```bash
npm install react-redux
The recommended way to start new apps with React Redux is by using the [official Redux+JS template](https://github.com/reduxjs/cra-template-redux) for [Create React App](https://github.com/facebook/create-react-app), which takes advantage of [Redux Toolkit](https://redux-toolkit.js.org/).

```sh
npx create-react-app my-app --template redux
```

or
### An Existing React App

To use React Redux with your React app, install it as a dependency:

```bash
# If you use npm:
npm install react-redux

# Or if you use Yarn:
yarn add react-redux
```

Expand Down
4 changes: 4 additions & 0 deletions docs/using-react-redux/accessing-store.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ by a single default context object instance generated by `React.createContext()`
React Redux's `<Provider>` component uses `<ReactReduxContext.Provider>` to put the Redux store and the current store
state into context, and `connect` uses `<ReactReduxContext.Consumer>` to read those values and handle updates.

## Using the `useStore` Hook

The [`useStore` hook](../api/hooks.md#useStore) returns the current store instance from the default `ReactReduxContext`. If you truly need to access the store, this is the recommended approach.

## Providing Custom Context

Instead of using the default context instance from React Redux, you may supply your own custom context instance.
Expand Down
21 changes: 15 additions & 6 deletions src/components/connectAdvanced.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,16 @@ export default function connectAdvanced(
const usePureOnlyMemo = pure ? useMemo : callback => callback()

function ConnectFunction(props) {
const [propsContext, forwardedRef, wrapperProps] = useMemo(() => {
const [
propsContext,
reactReduxForwardedRef,
wrapperProps
] = useMemo(() => {
// Distinguish between actual "data" props that were passed to the wrapper component,
// and values needed to control behavior (forwarded refs, alternate context instances).
// To maintain the wrapperProps object reference, memoize this destructuring.
const { forwardedRef, ...wrapperProps } = props
return [props.context, forwardedRef, wrapperProps]
const { reactReduxForwardedRef, ...wrapperProps } = props
return [props.context, reactReduxForwardedRef, wrapperProps]
}, [props])

const ContextToUse = useMemo(() => {
Expand Down Expand Up @@ -437,8 +441,13 @@ export default function connectAdvanced(
// Now that all that's done, we can finally try to actually render the child component.
// We memoize the elements for the rendered child component as an optimization.
const renderedWrappedComponent = useMemo(
() => <WrappedComponent {...actualChildProps} ref={forwardedRef} />,
[forwardedRef, WrappedComponent, actualChildProps]
() => (
<WrappedComponent
{...actualChildProps}
ref={reactReduxForwardedRef}
/>
),
[reactReduxForwardedRef, WrappedComponent, actualChildProps]
)

// If React sees the exact same element reference as last time, it bails out of re-rendering
Expand Down Expand Up @@ -472,7 +481,7 @@ export default function connectAdvanced(
props,
ref
) {
return <Connect {...props} forwardedRef={ref} />
return <Connect {...props} reactReduxForwardedRef={ref} />
})

forwarded.displayName = displayName
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function useSelectorWithStoreAndSubscription(
latestSubscriptionCallbackError.current = err
}

forceRender({})
forceRender()
}

subscription.onStateChange = checkForUpdates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ propagated to connected components, so that this works as expected by default.
However, there may be certain use cases where you may need to customize how the store and state are propagated to
connected components, or access the store directly. Here are some examples of how to do this.

## Using the `useStore` Hook

The [`useStore` hook](../api/hooks.md#useStore) returns the current store instance from the default `ReactReduxContext`. If you truly need to access the store, this is the recommended approach.

## Understanding Context Usage

Internally, React Redux uses [React's "context" feature](https://reactjs.org/docs/context.html) to make the
Expand Down

0 comments on commit ee80685

Please sign in to comment.