I'm trying to fetch appointment
data from my rails-api backend using the createAsyncThunk function. When I
console.log('appointmentDate', appointmentDate);
console.log('doctorId', doctorId);
console.log('userId', userId);
After clicking the submit button to create a new appointment; I get:
appointmentDate => 2021-07-30 which is fine
doctorId => 2 which is also fine.
userId => undefined which is not what I'm expecting. I expected a number just like doctorId
I have tested the backend with postman and everything is fine. And since I can't fetch the correct data. I can't create an appointment
when I submit the form
This is how I'm destructuring the user
state before adding it to the postAppointment
action creator for dispatch
const { data: userData } = useSelector((state) => state.user);
const { userId } = userData;
since `user_Id` is part of the `user` state in my `store`. I can destructure it as above and add it to my `dispatch`.
And this is how I'm dispatching it inside the NewAppointment
component
dispatch(postAppointments({ userId, doctorId, appointmentDate }))
.then(() => {
setSuccessful(true);
alert.show('Appointment created', {
type: 'success',
timeout: 2000,
});
setLoading(false);
})
.catch((error) => {
console.log(error.message);
setSuccessful(false);
});
I don't know what I'm missing with the user
destructuring and dispatching the action creator
?
Here are the other codes
src/redux/appointmentsSlice
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import API from '../api/api';
export const postAppointments = createAsyncThunk(
'appointments/postAppointments',
async (
{
userId, appointmentDate, doctorId,
},
) => {
console.log('appointmentDate', appointmentDate);
console.log('doctorId', doctorId);
console.log('userId', userId);
const response = await fetch(`${API}/users/${userId}/appointments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({
appointmentDate,
doctorId,
userId,
}),
});
const data = await response.json();
console.log('appointmentsData', data);
if (!response.ok) throw new Error(data.failure);
localStorage.setItem('token', data.jwt);
console.log('localstorageData', data);
return data;
},
);
export const appointmentsSlice = createSlice({
name: 'appointments',
initialState: {
loading: false,
error: null,
data: [],
},
extraReducers: {
[postAppointments.pending]: (state) => {
state.loading = true;
},
[postAppointments.rejected]: (state, action) => {
state.loading = false;
state.error = action.error.message;
},
[postAppointments.fulfilled]: (state, action) => {
state.loading = false;
state.data = action.payload;
},
},
});
export default appointmentsSlice.reducer;
src/components/NewAppointment
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Redirect } from 'react-router-dom';
import { postAppointments } from '../redux/appointmentsSlice';
import { getDoctors } from '../redux/doctorsSlice';
const NewAppointment = () => {
const [appointmentDate, setAppointmentDate] = useState('');
const [doctorId, setDoctorId] = useState('');
const [successful, setSuccessful] = useState(false);
const [loading, setLoading] = useState(false);
const { data: userData } = useSelector((state) => state.user);
const { userId } = userData;
console.log('userData', userData);
const dispatch = useDispatch();
const { data, error } = useSelector((state) => state.doctors);
console.log('data', data);
useEffect(() => {
if (data === null && userData) {
dispatch(getDoctors())
.then(() => {
loading(false);
})
.catch(() => {
// setError('Unable to get doctors list');
});
}
}, [data, dispatch]);
const onChangeDoctorId = (e) => {
const doctorId = e.target.value;
setDoctorId(doctorId);
console.log('doctorUnchange', doctorId);
};
const onChangeAppointmentDate = (e) => {
const appointmentDate = e.target.value;
setAppointmentDate(appointmentDate);
console.log('apptntmentonchange', appointmentDate);
};
const handleBooking = (e) => {
e.preventDefault();
setSuccessful(false);
// eslint-disable-next-line no-underscore-dangle
dispatch(postAppointments({ userId, doctorId, appointmentDate }))
.then(() => {
setSuccessful(true);
alert.show('Appointment created', {
type: 'success',
timeout: 2000,
});
setLoading(false);
})
.catch((error) => {
console.log(error.message);
setSuccessful(false);
});
};
console.log('data now', data);
const options = data && (
data.map((doctor) => (
<option
key={doctor.id}
value={doctor.id}
>
{doctor.name}
</option>
))
);
if (!userData) {
return <Redirect to="/login" />;
}
if (successful) {
return <Redirect to="/appointments" />;
}
return (
<div className="col-md-12">
<div className="card card-container">
<form onSubmit={handleBooking}>
{ !successful && (
<div>
<div className="form-group create">
<label htmlFor="appointmentDate" className="control-label">
Appointment Date
<input
type="date"
className="form-control"
name="appointmentDate"
id="appointmentDate"
required
value={appointmentDate}
onChange={onChangeAppointmentDate}
/>
</label>
</div>
<div className="form-group create">
<label htmlFor="doctorId">
Select from list:
<select className="form-control" id="doctorId" onChange={onChangeDoctorId} value={doctorId}>
{loading ? <option>Loading..</option> : options }
</select>
</label>
</div>
<div className="form-group create">
<button className="btn btn-primary btn-block" disabled={loading} type="submit">
{loading && (
<span className="spinner-border spinner-border-sm" />
)}
<span>Book</span>
</button>
</div>
</div>
)}
{error && (
<div className="form-group">
<div className={successful ? 'alert alert-success' : 'alert alert-danger'} role="alert">
{error}
</div>
</div>
)}
</form>
</div>
</div>
);
};
export default NewAppointment;
And the API url
returns undefined for the userId variable
as shown below
POST https://agile-escarpment-87534.herokuapp.com/api/v1/users/undefined/appointments 404 (Not Found)
This is my first project using createAsyncThunk
and still trying to understand how it works. I have also checked similar posts, but none solved my issue. Any support or constructive criticism is welcome.
Comments
Post a Comment