【发布时间】:2021-10-06 06:55:14
【问题描述】:
我正在尝试使用 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
我已经用邮递员测试了后端,一切都很好。而且由于我无法获取正确的数据。当我提交 form 时,我无法创建 appointment
这就是我在将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 返回未定义,如下所示
POST https://agile-escarpment-87534.herokuapp.com/api/v1/users/undefined/appointments 404 (Not Found)
这是我使用createAsyncThunk 的第一个项目,并且仍在尝试了解它是如何工作的。我也检查过类似的帖子,但没有一个能解决我的问题。
欢迎任何支持或建设性的批评。
【问题讨论】:
-
你检查
userId里面的userData是否真的是属性集? -
@Kelvin,如果我得到你的问题。
user_id是 userData 对象属性的一部分,采用 1、2、3 等值。我从控制台 userData {username: "test_user", user_id: 1, jwt: "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.7kO493fIYp8enGgfwPpWpZfc5BwmrZNx6arNGZWtS94"} 得到这个。登录后 -
你的问题。它记录
user_id,但您的代码使用 `userId´。 -
但是 JavaScripts 允许骆驼大小写
userId而不是下划线user_id。那么我该怎么做呢? -
是否允许使用
user_id?它允许使用下划线甚至美元符号。 我认为它甚至可以接受任何非特殊 (ANSII/JS) 字符的 unicode 字符。 您绝对可以使用userData.user_id。即使这不可能,您也可以使用userData['user_id']来按任何字符串进行索引,同时使用\'和\\转义每个'和\。
标签: javascript reactjs react-redux fetch-api