I’m implementing a registration page to my nodejs api. With createAsyncThunk I implemented the function to fetch the user data and update the state. The api works correctly, in fact it returns the created user data in the payload when the action is dispatched. But the user state is not updated and stays the initial state.
Here the user slice code:
JavaScript
x
74
74
1
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
2
import axios from 'axios'
3
4
const initialState = {
5
username: null,
6
email: null,
7
password: null,
8
gamesPlayed: null,
9
gamesWon: null,
10
gamesLost: null,
11
draws: null,
12
loading: false,
13
error: null
14
}
15
16
const serializeAndStringify = obj => {
17
const seen = []
18
JSON.stringify(
19
obj,
20
(key, val) => {
21
if(val != null && typeof val === 'object') {
22
if(seen.indexOf(val) >= 0)
23
return
24
seen.push(val)
25
}
26
return val
27
}
28
)
29
return seen[0]
30
}
31
32
export const fetchUserData = (requestUrl, userData) =>
33
createAsyncThunk(
34
'userAuth',
35
async () =>
36
axios.post(requestUrl, serializeAndStringify(userData))
37
)
38
39
const userSlice = createSlice({
40
name: 'user',
41
initialState,
42
reducers: {
43
victory (state) {
44
state.gamesPlayed++
45
state.gamesWon++
46
},
47
defeat (state) {
48
state.gamesPlayed++
49
state.gamesLost++
50
},
51
draw (state) {
52
state.gamesPlayed++
53
state.draws++
54
}
55
},
56
extraReducers: {
57
[fetchUserData.pending]: (state, action) => {
58
state.loading = true
59
},
60
[fetchUserData.fullFilled]: (state, { payload }) => {
61
state.loading = false
62
state.username = payload.data.username
63
state.email = payload.data.email
64
state.password = payload.data.password
65
},
66
[fetchUserData.rejected]: (state, action) => {
67
state.loading = false
68
state.error = action.payload
69
}
70
}
71
})
72
73
export default userSlice.reducer
74
The store.js:
JavaScript
1
23
23
1
import { configureStore } from '@reduxjs/toolkit'
2
import logger from 'redux-logger'
3
import thunk from 'redux-thunk'
4
5
import userReducer from './user'
6
7
const reducer = {
8
user: userReducer
9
}
10
11
const middlewares = [thunk]
12
13
if(process.env.NODE_ENV === 'development')
14
middlewares.push(logger)
15
16
const store = configureStore({
17
reducer,
18
middleware: middlewares,
19
devTools: process.env.NODE_ENV !== 'production',
20
})
21
22
export default store
23
The registration page:
JavaScript
1
73
73
1
import { Fragment } from 'react'
2
import { useNavigate } from 'react-router'
3
import { useDispatch } from 'react-redux'
4
5
import { fetchUserData } from '../../redux/user.js'
6
7
import './register.styles.scss'
8
9
const RegisterPage = () => {
10
const navigate = useNavigate()
11
const dispatch = useDispatch()
12
13
const handleSubmit = event => {
14
event.preventDefault()
15
const { username, email, password } = event.target
16
let userData
17
let requestUrl = '/auth/'
18
19
if(username) {
20
userData = {
21
username: username.value,
22
email: email.value,
23
password: password.value
24
}
25
requestUrl += 'registration'
26
} else {
27
userData = {
28
email: email.value,
29
password: password.value
30
}
31
requestUrl += 'login'
32
}
33
dispatch(fetchUserData(requestUrl, userData)())
34
}
35
36
return (
37
<Fragment>
38
<div className='register-page'>
39
<form className='container' onSubmit={handleSubmit}>
40
<span>WELCOME BACK</span>
41
<input name='email' required type='email' placeholder='Email' />
42
<input name='password' required type='password' minLength='8' placeholder='Password' />
43
<div className='button-wrapper'>
44
<button type='submit'>LOG IN</button>
45
<button className='google-button'>
46
<a href='http://localhost:4000/auth/google'>
47
LOG IN WITH GOOGLE
48
</a>
49
</button>
50
</div>
51
</form>
52
<form className='container' onSubmit={handleSubmit}>
53
<span>REGISTER</span>
54
<input name='username' required type='text' placeholder='Username' />
55
<input name='email' required type='email' placeholder='Email' />
56
<input name='password' required type='password' minLength='8' placeholder='Password' />
57
<div className='button-wrapper'>
58
<button type='submit'>SIGN IN</button>
59
<button className='google-button'>
60
<a href='http://localhost:4000/auth/google'>
61
SIGN IN WITH GOOGLE
62
</a>
63
</button>
64
</div>
65
</form>
66
</div>
67
<button onClick={() => navigate('/', {replace: true})}>Go back</button>
68
</Fragment>
69
)
70
}
71
72
export default RegisterPage
73
Advertisement
Answer
I modified the request field in this way:
JavaScript
1
8
1
export const fetchUserData = createAsyncThunk(
2
'userAuth',
3
async ({ requestUrl, userData }) => {
4
const resp = await axios.post(requestUrl, serializeAndStringify(userData))
5
return resp.data
6
}
7
)
8
And instead of writing fulfilled I had written fullFilled
Old code:
JavaScript
1
2
1
[fetchUserData.fullFilled]: (state, { payload }) =>
2
New code:
JavaScript
1
2
1
[fetchUserData.fulfilled]: (state, { payload }) =>
2
And now it works