-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
docs: demonstrate selector usage in playground #352
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| import * as React from 'react'; | ||
| import { connect } from 'react-redux'; | ||
|
|
||
| import { RootState } from '../store/root-reducer'; | ||
| import { countersActions } from '../features/counters'; | ||
| import { getCounter } from '../features/counters/selectors'; | ||
| import FCCounter from '../components/fc-counter'; | ||
|
|
||
| // mapStateToProps using a selector to derive counter value from global state | ||
| // The selector handles the adaptation from RootState to the value the component needs | ||
| const mapStateToProps = (state: RootState) => ({ | ||
| count: getCounter(state), | ||
| }); | ||
|
|
||
| const mapDispatchToProps = { | ||
| onIncrement: countersActions.increment, | ||
| onDecrement: countersActions.decrement, | ||
| }; | ||
|
Comment on lines
+15
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| export default connect( | ||
| mapStateToProps, | ||
| mapDispatchToProps | ||
| )(FCCounter); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import * as React from 'react'; | ||
| import { connect } from 'react-redux'; | ||
|
|
||
| import { RootState } from '../store/root-reducer'; | ||
| import { todosActions } from '../features/todos'; | ||
| import { | ||
| getTodosFilteredList, | ||
| getTodosFilter, | ||
| } from '../features/todos/selectors'; | ||
| import TodoList from '../components/todo-list'; | ||
|
|
||
| // mapStateToProps using selectors to derive data from global state. | ||
| // Selectors encapsulate the knowledge of the state shape and | ||
| // any derived computations (e.g., filtering). | ||
| const mapStateToProps = (state: RootState) => ({ | ||
| todos: getTodosFilteredList(state), | ||
| filter: getTodosFilter(state), | ||
| }); | ||
|
|
||
| const mapDispatchToProps = { | ||
| toggle: todosActions.toggle, | ||
| }; | ||
|
|
||
| export default connect( | ||
| mapStateToProps, | ||
| mapDispatchToProps | ||
| )(TodoList); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,3 +1,29 @@ | ||||||||||||||||||
| import { CountersState } from './reducer'; | ||||||||||||||||||
| import { createSelector } from 'reselect'; | ||||||||||||||||||
| import { RootState } from '../../store/root-reducer'; | ||||||||||||||||||
|
|
||||||||||||||||||
| export const getReduxCounter = (state: CountersState) => state.reduxCounter; | ||||||||||||||||||
| /** | ||||||||||||||||||
| * Selectors are used to derive data from the Redux store state. | ||||||||||||||||||
| * They are composed using `createSelector` from the `reselect` library. | ||||||||||||||||||
| * | ||||||||||||||||||
| * To adapt global state (RootState) to feature-specific state, we use | ||||||||||||||||||
| * a "input selector" that picks the feature slice from the global state. | ||||||||||||||||||
| */ | ||||||||||||||||||
|
|
||||||||||||||||||
| // Input selector: picks the counters feature slice from global state | ||||||||||||||||||
| const getCounters = (state: RootState) => state.counters; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Derived selectors | ||||||||||||||||||
| export const getCountersState = createSelector( | ||||||||||||||||||
| getCounters, | ||||||||||||||||||
| counters => counters | ||||||||||||||||||
| ); | ||||||||||||||||||
|
|
||||||||||||||||||
| export const getCounter = createSelector( | ||||||||||||||||||
| getCounters, | ||||||||||||||||||
| counters => counters.counter | ||||||||||||||||||
| ); | ||||||||||||||||||
|
Comment on lines
+21
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The state shape defined in
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| export const getCounterHasValue = createSelector( | ||||||||||||||||||
| getCounter, | ||||||||||||||||||
| counter => counter > 0 | ||||||||||||||||||
| ); | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,19 +1,44 @@ | ||||||||||||||||||||||||||||||||||||||||||
| import { createSelector } from 'reselect'; | ||||||||||||||||||||||||||||||||||||||||||
| import { RootState } from '../../store/root-reducer'; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| import { TodosState } from './reducer'; | ||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * Selectors are used to derive data from the Redux store state. | ||||||||||||||||||||||||||||||||||||||||||
| * They are composed using `createSelector` from the `reselect` library. | ||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||
| * To adapt global state (RootState) to feature-specific state, we use | ||||||||||||||||||||||||||||||||||||||||||
| * a "input selector" that picks the feature slice from the global state. | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export const getTodos = (state: TodosState) => state.todos; | ||||||||||||||||||||||||||||||||||||||||||
| // Input selector: picks the todos feature slice from global state | ||||||||||||||||||||||||||||||||||||||||||
| const getTodos = (state: RootState) => state.todos; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export const getTodosFilter = (state: TodosState) => state.todosFilter; | ||||||||||||||||||||||||||||||||||||||||||
| // Derived selectors | ||||||||||||||||||||||||||||||||||||||||||
| export const getTodosState = createSelector( | ||||||||||||||||||||||||||||||||||||||||||
| getTodos, | ||||||||||||||||||||||||||||||||||||||||||
| todos => todos | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export const getFilteredTodos = createSelector(getTodos, getTodosFilter, (todos, todosFilter) => { | ||||||||||||||||||||||||||||||||||||||||||
| switch (todosFilter) { | ||||||||||||||||||||||||||||||||||||||||||
| case 'completed': | ||||||||||||||||||||||||||||||||||||||||||
| return todos.filter(t => t.completed); | ||||||||||||||||||||||||||||||||||||||||||
| case 'active': | ||||||||||||||||||||||||||||||||||||||||||
| return todos.filter(t => !t.completed); | ||||||||||||||||||||||||||||||||||||||||||
| export const getTodosList = createSelector( | ||||||||||||||||||||||||||||||||||||||||||
| getTodos, | ||||||||||||||||||||||||||||||||||||||||||
| todos => todos.todos | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||
| return todos; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||
| export const getTodosFilter = createSelector( | ||||||||||||||||||||||||||||||||||||||||||
| getTodos, | ||||||||||||||||||||||||||||||||||||||||||
| todos => todos.filter | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The state shape defined in
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export const getTodosFilteredList = createSelector( | ||||||||||||||||||||||||||||||||||||||||||
| getTodosList, | ||||||||||||||||||||||||||||||||||||||||||
| getTodosFilter, | ||||||||||||||||||||||||||||||||||||||||||
| (todos, filter) => todos.filter(todo => { | ||||||||||||||||||||||||||||||||||||||||||
| switch (filter) { | ||||||||||||||||||||||||||||||||||||||||||
| case 'active': | ||||||||||||||||||||||||||||||||||||||||||
| return !todo.done; | ||||||||||||||||||||||||||||||||||||||||||
| case 'completed': | ||||||||||||||||||||||||||||||||||||||||||
| return todo.done; | ||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+34
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The component
FCCounteris exported as a named export (export const FCCounter) inplayground/src/components/fc-counter.tsx, not as a default export. You should use a named import here to avoid import errors.