I am trying to get a list of data called packages and put it in a table. Added filter and sorting to it.
- I get packages from pakageList reducer
- Assign to data state
- Then add soring and filtering logic and assign data to variable called filteredPackages Everything seems fine but when the page initially loads the contents of the table is empty i.e, the data state is empty. This happens while adding or deleting a package and render occurs as well. Once I go back and come to this screen again the data loads. The data is present in the packages which I get from reducers but it does not get assigned to the data state. Can anyone try checking and let me know what can be done here. Sorry if my code is not good. Thanks in advance.
Skipping code which is not necessary
JavaScript
x
189
189
1
const PackageScreen = ({ match }) => {
2
const [ order, setOrder ] = useState('ASC')
3
const packageList = useSelector(state => state.packageList)
4
const { loading, error, packages } = packageList
5
6
const packageCreate = useSelector(state => state.packageCreate)
7
const { loading:loadingCreate , error:errorCreate , success: successCreate, package: createdPackage } = packageCreate
8
9
const packageDelete = useSelector(state => state.packageDelete)
10
const { loading:loadingDelete , error:errorDelete , success: successDelete } = packageDelete
11
12
const [ data, setData ] = useState([])
13
14
useEffect(() => {
15
dispatch({type: PACKAGE_CREATE_RESET})
16
17
if(!userInfo || !userInfo.isAdmin){
18
navigate('/')
19
}
20
21
setName('')
22
setMaxDays(0)
23
setMaxUsers(0)
24
dispatch(listPackages())
25
26
setData(packages)
27
28
}, [dispatch, userInfo, successCreate, successDelete, navigate] )
29
30
31
32
const sorting = (col) => {
33
if(order === 'ASC'){
34
const sorted = [data].sort((a,b) =>
35
a[col].toString().toLowerCase() > b[col].toString().toLowerCase() ? 1 : -1
36
)
37
setData(sorted)
38
setOrder('DSC')
39
}
40
if(order === 'DSC'){
41
const sorted = [data].sort((a,b) =>
42
a[col].toString().toLowerCase() < b[col].toString().toLowerCase() ? 1 : -1
43
)
44
setData(sorted)
45
setOrder('ASC')
46
}
47
}
48
49
function search(data) {
50
return data.filter((pack) =>
51
pack.packageName.toLowerCase().indexOf(q.toLowerCase()) > -1
52
)
53
}
54
55
const filteredPackages = search(data)
56
57
const submitHandler = (e) =>{
58
e.preventDefault()
59
dispatch(createPackage({
60
packageName: name,
61
maxDaysAllowed : maxDays * 30,
62
maxUserAllowed : maxUsers
63
}))
64
}
65
66
const deleteHandler = (id) =>{
67
if(window.confirm('Are you sure you want to delete?')){
68
dispatch(deletePackage(id))
69
}
70
}
71
72
73
return(
74
<>
75
<Link to='/' className='btn btn-dark my-3'>Go Back</Link>
76
<h1>Add Package</h1>
77
78
<Form onSubmit={submitHandler}>
79
<Row className='my-3' >
80
<Col>
81
<Form.Group className="mb-3" controlId='name'>
82
<FloatingLabel controlId="floatingInput" label="Package Name" className="mb-3">
83
<Form.Control type="text" placeholder="Package name"
84
value={name}
85
onChange = {(e)=> setName(e.target.value)}
86
/>
87
</FloatingLabel>
88
</Form.Group>
89
</Col>
90
<Col>
91
<Form.Group controlId='maxUsers'>
92
<FloatingLabel controlId="floatingSelect" label="Max. allowed users">
93
<Form.Control as='select' value={maxUsers}
94
onChange={(e) => setMaxUsers(e.target.value)}>
95
{/*<Form.Select aria-label="Floating label select example">*/}
96
<option>Select number of users</option>
97
<option value="3">3</option>
98
<option value="5">5</option>
99
<option value="10">10</option>
100
{/*</Form.Select>*/}
101
</Form.Control>
102
</FloatingLabel>
103
</Form.Group>
104
</Col>
105
<Col>
106
<Form.Group controlId='maxDays'>
107
<FloatingLabel controlId="floatingSelect" label="Package Limit">
108
<Form.Control as='select' value={maxDays}
109
onChange={(e) => setMaxDays(e.target.value)}>
110
{/*<Form.Select aria-label="Floating label select example">*/}
111
<option>Select Period</option>
112
<option value="1">1 Month</option>
113
<option value="3">3 Months</option>
114
<option value="6">6 Months</option>
115
<option value="12">1 year</option>
116
{/*</Form.Select>*/}
117
</Form.Control>
118
</FloatingLabel>
119
</Form.Group>
120
</Col>
121
122
</Row>
123
<Button type='submit' variant='primary'>
124
Save
125
</Button>
126
</Form>
127
128
<h2 className='mt-4'>Package List</h2>
129
<div className='d-flex'>
130
<div className='p-2'>
131
<div className='searchTable'>
132
<InputGroup className="me-2 my-2">
133
<InputGroup.Text>Search</InputGroup.Text>
134
<FormControl aria-label="Search"
135
value={q} onChange={(e) => setQ(e.target.value)}
136
/>
137
</InputGroup>
138
</div>
139
</div>
140
</div>
141
142
143
144
{ loading ? <Loader />
145
: error ? <Message variant='danger'>{error}</Message>
146
: (
147
<div>
148
<Table striped bordered hover responsive='md' className='table-sm bg-light' id="table-to-xls">
149
<thead>
150
<tr>
151
<th onClick={() => sorting('packageName')} ><span className='btn'>Package Name</span></th>
152
<th onClick={() => sorting('maxUserAllowed')} ><span className='btn'>Maximum Users</span></th>
153
<th onClick={() => sorting('maxDaysAllowed')} ><span className='btn'>Maximum Days</span></th>
154
<th><span className='btn'>Action</span></th>
155
</tr>
156
</thead>
157
<tbody>
158
{filteredPackages.map(pack => (
159
<tr key={pack._id} >
160
<td>{pack.packageName}</td>
161
<td>{pack.maxUserAllowed}</td>
162
<td>{pack.maxDaysAllowed}</td>
163
<td>
164
{/*<LinkContainer to={`/admin/product/${product._id}/edit`}>*/}
165
<Button variant='info' className='btn-sm mx-1' disabled>
166
<i className='fas fa-edit'></i>
167
</Button>
168
{/*</LinkContainer>*/}
169
<Button variant='danger' className='btn-sm'
170
onClick={()=> deleteHandler(pack._id)}
171
>
172
<i className='fas fa-trash'></i>
173
</Button>
174
</td>
175
</tr>
176
)) }
177
</tbody>
178
</Table>
179
</div>
180
)
181
}
182
</>
183
)
184
}
185
186
187
188
export default PackageScreen
189
data and filteredPackage both are empty at initial renders. I tried the below in useEffect but no luck
JavaScript
1
19
19
1
useEffect(() => {
2
dispatch({type: PACKAGE_CREATE_RESET})
3
4
if(!userInfo || !userInfo.isAdmin){
5
navigate('/')
6
}
7
8
setName('')
9
setMaxDays(0)
10
setMaxUsers(0)
11
12
dispatch(listPackages())
13
**const fetchData = async()=>{
14
await setData(packages)
15
}
16
fetchData()**
17
18
}, [dispatch, userInfo, successCreate, successDelete, navigate] )
19
Please let me know if you need further details.
Advertisement
Answer
Make a const for packages and assign this to your data state
JavaScript
1
4
1
const packages = useSelector(state => state.packageList.packages)
2
3
const [ data, setData ] = useState(packages)
4
and write a useEffect that updates your data state when ever your package store value renders
JavaScript
1
4
1
useEffect(()=>{
2
setData([packages])
3
},[packages])
4