File tree Expand file tree Collapse file tree 7 files changed +165
-5
lines changed Expand file tree Collapse file tree 7 files changed +165
-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+
6+ function UsersComponent ( {
7+ addUser,
8+ deleteUser
9+ } ) {
10+ return (
11+ < Page >
12+ < h2 >
13+ Redux Toolkit - Users
14+ </ h2 >
15+
16+ < p > Testing page re-renders and data rendering from a redux store inside a deeply-nested component.</ p >
17+
18+ < button onClick = { addUser }
19+ style = { { marginTop : '24px' } } >
20+ Add User
21+ </ button >
22+
23+ < br /> < br />
24+
25+ { /** A deeply-nested component */ }
26+ < Card >
27+ < Card >
28+ < Card >
29+ < Card >
30+ < Card >
31+ < Card >
32+ < UserListComponent deleteUser = { deleteUser } />
33+ </ Card >
34+ </ Card >
35+ </ Card >
36+ </ Card >
37+ </ Card >
38+ </ Card >
39+ </ Page >
40+ )
41+ }
42+
43+ UsersComponent . propTypes = {
44+ addUser : PropTypes . func ,
45+ deleteUser : PropTypes . func
46+ }
47+
48+ 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+
4+ import UsersComponent from '@/components/users'
5+
6+ function Users ( ) {
7+ const dispatch = useDispatch ( )
8+
9+ const addUser = ( ) => {
10+ dispatch ( userReceived ( {
11+ text : 'User anonymous!'
12+ } ) )
13+ }
14+
15+ const deleteUser = ( id ) => {
16+ dispatch ( userDelete ( id ) )
17+ }
18+
19+ return (
20+ < UsersComponent
21+ addUser = { addUser }
22+ deleteUser = { deleteUser }
23+ />
24+ )
25+ }
26+
27+ export default Users
You can’t perform that action at this time.
0 commit comments