File tree Expand file tree Collapse file tree 7 files changed +194
-5
lines changed Expand file tree Collapse file tree 7 files changed +194
-5
lines changed Original file line number Diff line number Diff line change 1+ import PropTypes from 'prop-types'
2+ import Page from '@/common/layout/page'
3+ import Card from '@/common/ui/card'
4+ import UserListComponent from '@/domain/users/userlist'
5+ import TodoListComponent from '@/domain/redux/todolist'
6+
7+ function UsersComponent ( {
8+ addUser,
9+ deleteUser,
10+ deleteTodo,
11+ addTodo
12+ } ) {
13+ return (
14+ < Page >
15+ < h2 >
16+ Redux Toolkit - Users
17+ </ h2 >
18+
19+ < p > Testing page re-renders and data rendering from multiple redux stores (Users and ToDo) inside regular and deeply-nested components.</ p >
20+
21+ < button onClick = { addUser }
22+ style = { { marginTop : '24px' } } >
23+ Add User
24+ </ button >
25+
26+ < br /> < br />
27+ < h3 > Users</ h3 >
28+ < br />
29+
30+ { /** A deeply-nested component */ }
31+ < Card >
32+ < Card >
33+ < Card >
34+ < Card >
35+ < Card >
36+ < Card >
37+ < UserListComponent deleteUser = { deleteUser } />
38+ </ Card >
39+ </ Card >
40+ </ Card >
41+ </ Card >
42+ </ Card >
43+ </ Card >
44+
45+ < br />
46+ < button onClick = { addTodo }
47+ style = { { marginTop : '24px' } } >
48+ Add Todo
49+ </ button >
50+
51+ < br /> < br />
52+ < h3 > ToDo</ h3 >
53+
54+ < TodoListComponent deleteTodo = { deleteTodo } />
55+ </ Page >
56+ )
57+ }
58+
59+ UsersComponent . propTypes = {
60+ addUser : PropTypes . func ,
61+ deleteUser : PropTypes . func
62+ }
63+
64+ export default UsersComponent
Original file line number Diff line number Diff line change 1+ import PropTypes from 'prop-types'
2+ import { useSelector } from 'react-redux'
3+
4+ function UserListComponent ( { deleteUser } ) {
5+ const { ids, entities : users } = useSelector ( state => state . users )
6+
7+ return (
8+ < ul style = { { marginTop : '24px' } } >
9+ { ( ids ) . map ( ( ( id , index ) => (
10+ < li key = { index } >
11+ < span > id: { users [ id ] . id } , { users [ id ] . text } </ span >
12+ < span >
13+ < button onClick = { ( ) => deleteUser ( id ) } >
14+ [ x ]
15+ </ button >
16+ </ span >
17+ </ li >
18+ ) ) ) }
19+ </ ul >
20+ )
21+ }
22+
23+ UserListComponent . propTypes = {
24+ deleteUser : PropTypes . func
25+ }
26+
27+ export default UserListComponent
Original file line number Diff line number Diff line change 1+ const STATES = {
2+ IDLE : 'idle' ,
3+ PENDING : 'pending'
4+ }
5+
6+ export {
7+ STATES
8+ }
Original file line number Diff line number Diff line change @@ -2,10 +2,12 @@ import { combineReducers } from 'redux'
22import { configureStore } from '@reduxjs/toolkit'
33
44import todoSlice from '@/lib/store/todos/todoSlice'
5+ import usersSlice from '@/lib/store/users/usersSlice'
56
67// Reducers
78const combinedReducer = combineReducers ( {
8- todos : todoSlice
9+ todos : todoSlice ,
10+ users : usersSlice
911} )
1012
1113const rootReducer = ( state , action ) => {
Original file line number Diff line number Diff line change @@ -7,10 +7,7 @@ import {
77 createEntityAdapter
88} from '@reduxjs/toolkit'
99
10- const STATES = {
11- IDLE : 'idle' ,
12- PENDING : 'pending'
13- }
10+ import { STATES } from '@/lib/store/constants'
1411
1512// Entiti adapter
1613const todosAdapter = createEntityAdapter ( {
Original file line number Diff line number Diff line change 1+ // Notes:
2+ // https://redux.js.org/tutorials/essentials/part-6-performance-normalization#normalized-state-structure
3+ // https://redux.js.org/tutorials/essentials/part-6-performance-normalization#optimizing-the-posts-list
4+
5+ import {
6+ createSlice ,
7+ createEntityAdapter
8+ } from '@reduxjs/toolkit'
9+
10+ import { STATES } from '@/lib/store/constants'
11+
12+ // Entiti adapter
13+ const usersAdapter = createEntityAdapter ( {
14+ selectId : ( user ) => user . id
15+ } )
16+
17+ // Slice
18+ const usersSlice = createSlice ( {
19+ name : 'users' ,
20+ initialState : usersAdapter . getInitialState ( {
21+ loading : STATES . IDLE ,
22+ error : '' ,
23+ success : '' ,
24+ todo : null
25+ } ) ,
26+ reducers : {
27+ userReceived ( state , action ) {
28+ const id = Math . random ( ) . toString ( 36 ) . substring ( 2 , 8 )
29+
30+ state . loading = STATES . IDLE
31+ state . todo = { ...action . payload , id }
32+ usersAdapter . addOne ( state , state . todo )
33+
34+ } ,
35+ userDelete ( state , action ) {
36+ usersAdapter . removeOne ( state , action . payload )
37+ } ,
38+ usersReceived ( state , action ) {
39+ state . loading = STATES . IDLE
40+ usersAdapter . setAll ( state , action . payload )
41+ }
42+ }
43+ } )
44+
45+ export const {
46+ userReceived,
47+ usersReceived,
48+ userDelete
49+ } = usersSlice . actions
50+
51+ export default usersSlice . reducer
Original file line number Diff line number Diff line change 1+ import { useDispatch } from 'react-redux'
2+ import { userReceived , userDelete } from '@/lib/store/users/usersSlice'
3+ import { todoDelete , todoReceived } from '@/lib/store/todos/todoSlice'
4+
5+ import UsersComponent from '@/components/users'
6+
7+ function Users ( ) {
8+ const dispatch = useDispatch ( )
9+
10+ const addUser = ( ) => {
11+ dispatch ( userReceived ( {
12+ text : 'User anonymous!'
13+ } ) )
14+ }
15+
16+ const deleteUser = ( id ) => {
17+ dispatch ( userDelete ( id ) )
18+ }
19+
20+ const addTodo = ( ) => {
21+ dispatch ( todoReceived ( {
22+ text : 'Hello, world!'
23+ } ) )
24+ }
25+
26+ const deleteTodo = ( id ) => {
27+ dispatch ( todoDelete ( id ) )
28+ }
29+
30+ return (
31+ < UsersComponent
32+ addUser = { addUser }
33+ deleteUser = { deleteUser }
34+ deleteTodo = { deleteTodo }
35+ addTodo = { addTodo }
36+ />
37+ )
38+ }
39+
40+ export default Users
You can’t perform that action at this time.
0 commit comments