我正在尝试使用 createAsyncThunk 函数从我的 rails-api 后端获取 appointment
数据。当我
console.log('appointmentDate', appointmentDate);
console.log('doctorId', doctorId);
console.log('userId', userId);
点击提交按钮后创建一个新的约会;我得到:
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
我已经用邮递员测试了后端,一切都很好。而且由于我无法获取正确的数据。我在提交 appointment
form
这是我在将 user
状态添加到 postAppointment
操作创建者以进行调度之前对其进行解构的方式
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`.
这就是我在 NewAppointment
组件中调度它的方式
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);
});
我不知道在 user
解构和调度 action creator
时我错过了什么?
这里是其他代码
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;
并且 API url
为 userId variable
返回 undefined ,如下所示
POST https://agile-escarpment-87534.herokuapp.com/api/v1/users/undefined/appointments 404 (Not Found)
这是我第一个使用 createAsyncThunk
的项目,并且仍在尝试了解它的工作原理。我也检查过类似的帖子,但没有一个能解决我的问题。
欢迎任何支持或建设性的批评。
答案 0 :(得分:0)
您将需要此处的令牌
const { user_id, jwt } = userData;
将从 userData
中提取的令牌添加到 postAppointments
dispatch(postAppointments({ user_id, doctor_id, appointment_date, jwt }))
.then(() => {
setSuccessful(true);
alert.show('Appointment created', {
type: 'success',
timeout: 2000,
});
setLoading(false);
})
.catch((error) => {
console.log(error.message);
setSuccessful(false);
});
最后将令牌添加到获取请求中
export const postAppointments = createAsyncThunk(
'appointments/postAppointments',
async (
{
user_id, appointment_date, doctor_id, jwt
},
) => {
console.log('appointmentDate', appointment_date);
console.log('doctor_id', doctor_id);
console.log('user_id', user_id);
const response = await fetch(`${API}/appointments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
// this your missing header
Authorization: `Bearer ${jwt}`
},
body: JSON.stringify({
appointment_date,
doctor_id,
user_id,
}),
});
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;
},
);
这只是一个猜测..因为我没有实际的代码。
更新:
另一种写入该获取的方法:
fetch(`${API}/appointments`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${jwt}`
},
body: JSON.stringify({
appointment_date,
doctor_id,
user_id,
}),
}).then(response => {
response.json();
}).then(data => {
console.log('Success:', data);
localStorage.setItem('token', data.jwt);
}).catch((error) => {
// request just fail
throw new Error('Error:', error);
});
灵感来自:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch