Я получаю следующую ошибку, когда пытаюсь отобразить объект ({день} см. компонент реакции ниже), поступающий из базы данных:
Ошибка: объекты недействительны в качестве дочернего элемента React (найдено: объект с ключами {_id, дата, createdAt, updatedAt, __v}). Если вы хотели сделать коллекция дочерних элементов, вместо этого используйте массив.
Рассматриваемый объект выглядит следующим образом:
{
"_id": "5fdf554b88f52f520c93a16e",
"date": "2020-12-20T10:00:00.133Z",
"createdAt": "2020-12-20T13:44:43.934Z",
"updatedAt": "2020-12-20T13:44:43.934Z",
"__v": 0
}
И следующий мой код:
Маршрутизатор:
dayRouter.get(
'/:id',
expressAsyncHandler(async (req, res) => {
const day = await Day.findOne({ _id: req.params.id })
if (day) {
res.send(day);
} else {
res.status(404).send('Booking Not Found.');
}
})
);
export default dayRouter;
Редукс-действие:
export const detailsDate = (dayId) => async (dispatch) => {
try {
dispatch({ type: DATE_DETAILS_REQUEST, payload: dayId });
const { data } = await Axios.get(`/api/day/${dayId}`);
dispatch({ type: DATE_DETAILS_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: DATE_DETAILS_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
Redux-редуктор:
export function dateDetailsReducer(
state = {loading: true}, action) {
switch (action.type) {
case DATE_DETAILS_REQUEST:
return { loading: true };
case DATE_DETAILS_SUCCESS:
return { loading: false, day: action.payload };
case DATE_DETAILS_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
}
Реагирующий компонент:
import { useDispatch, useSelector } from 'react-redux';
import { detailsDate } from '../actions/dateAction';
function BookingConfirmationScreen(props) {
const dayId = props.match.params.id;
const dateDetails = useSelector((state) => state.dateDetails); //from Redux Store
const { day } = dateDetails;
const dispatch = useDispatch();
useEffect(() => {
dispatch(detailsDate(dayId));
return () => {};
}, [day,dispatch, dayId]);
return (
<h1> Booking {day}</h1>
)
}
export default BookingConfirmationScreen;
То, что мне нужно отобразить, на самом деле {day.date}, но я понимаю, что этот день на самом деле не определен. Именно тогда я понял, что есть проблема с {day}
день не определен, потому что вы получаете эти данные с сервера, поэтому рендеринг компонента выполняется быстрее, чем асинхронный вызов. Вот почему у вас есть загрузка в редукторе, она устанавливается в false, когда данные получены с сервера. Уничтожьте загрузку из состояния следующим образом:
const { day, loading } = dateDetails;
.
.
.
затем сделайте это, когда вы вернетесь:
if (loading)
return <div> loading.. </div>
return (
<h1> Booking {day.date}</h1>
)
Каждый раз, когда вы делаете вызов (запрос) к серверу, вы ждете ответа, и эта функция является асинхронной, асинхронный код принимает операторы за пределами основного потока программы, позволяя коду после асинхронного вызова выполняться немедленно без ожидания, в вашем случае компонент рендерится, не дожидаясь получения данных с сервера, поэтому сначала переменная day не определена (данные еще не получены). Я надеюсь, вы понимаете. Вот хорошая документация по этому поводу: rowanmanning.com/posts/javascript-for-beginners-async
Это еще лучше: blog.bitsrc.io/…
Это правда. Большое спасибо, это сработало. Я новичок и пытаюсь учиться. Могу ли я спросить вас, что вы имели в виду, говоря «вы получаете эти данные с сервера, поэтому рендеринг компонента выполняется быстрее, чем асинхронный вызов»? Я использую асинхронность в маршрутизаторе и действии. Спасибо