Skip to content

Add selector deps, perf info, and bump version #1253

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 1 commit into from
Apr 22, 2019
Merged
Show file tree
Hide file tree
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
48 changes: 43 additions & 5 deletions docs/api/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ From there, you may import any of the listed React Redux hooks APIs and use them
## `useSelector()`

```js
const result : any = useSelector(selector : Function)
const result : any = useSelector(selector : Function, deps : any[])
```

Allows you to extract data from the Redux store state, using a selector function.
Expand All @@ -43,6 +43,7 @@ The selector is approximately equivalent to the [`mapStateToProps` argument to `
However, there are some differences between the selectors passed to `useSelector()` and a `mapState` function:

- The selector may return any value as a result, not just an object. The return value of the selector will be used as the return value of the `useSelector()` hook.
- The selector function used will be based on the `deps` array. If no deps array is provided, the latest passed-in selector function will be used when the component renders, and also when any actions are dispatched before the next render. If a deps array is provided, the last saved selector will be used, and that selector will be overwritten whenever the deps array contents have changed.
- When an action is dispatched, `useSelector()` will do a shallow comparison of the previous selector result value and the current result value. If they are different, the component will be forced to re-render. If they are the same, they component will not re-render.
- The selector function does _not_ receive an `ownProps` argument. If you wish to use props within the selector function to determine what values to extract, you should call the React [`useMemo()`](https://reactjs.org/docs/hooks-reference.html#usememo) or [`useCallback()`](https://reactjs.org/docs/hooks-reference.html#usecallback) hooks yourself to create a version of the selector that will be re-created whenever the props it depends on change.

Expand Down Expand Up @@ -70,10 +71,10 @@ Using props to determine what to extract:
import React, { useCallback } from 'react'
import { useSelector } from 'react-redux'

export const TodoListItem = props => {
const todoSelector = useCallback(() => {
return state => state.todos[props.id]
}, [props.id])
export const TodoListItem = props => (
state => state.todos[props.id],
[props.id]
)

const todo = useSelector(todoSelector)

Expand Down Expand Up @@ -301,3 +302,40 @@ Some options for avoiding this problem:
- Try using the single function or array forms of `useActions()`

> **Note**: for more details on this problem, see [this comment and following in issue #1179](https://github.com/reduxjs/react-redux/issues/1179#issuecomment-482473235), as well as [this codesandbox that demonstrates the issue](https://codesandbox.io/s/7yjn3m9n96).

### Performance

As mentioned earlier, `useSelector()` will do basic shallow comparisons of return values when running the selector function after an action is dispatched. However, unlike `connect()`, `useSelector()` does not do anything to prevent your own function component from completing a re-render if the derived state has changed.

If further performance optimizations are necessary, you may consider either wrapping your function component in `React.memo(MyFunctionComponent)`, or using `useMemo()` to memoize the render output of your component:

```jsx
// Option 1: use React.memo() to keep the component from re-rendering

const CounterComponent = props => {
const counter = useSelector(state => state.counter)
return (
<div>
{props.name}: {counter}
</div>
)
}

export const MemoizedCounterComponent = React.memo(CounterComponent)

// Option 2: let the component re-render, but memoize output

export const CounterComponent = props => {
const counter = useSelector(state => state.counter)

const renderedChildren = useMemo(() => {
return (
<div>
{props.name}: {counter}
</div>
)
}, [props.name, counter])

return renderedChildren
}
```
2 changes: 1 addition & 1 deletion website/siteConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const siteConfig = {
* After that, 7.x will no longer appear in "pre-release" versions and we should remove this line
* More info: https://docusaurus.io/docs/en/versioning
*/
nextVersion: '7.1.0-alpha.0',
nextVersion: '7.1.0-alpha.1',

gaTrackingId: 'UA-130598673-2'
}
Expand Down