Мне всегда нравится добавлять свойства data
, error
, loading
и fetched
в состояние Redux для данных API. С помощью этих свойств вы точно знаете, что это за состояние.
Эти свойства должны быть установлены в ваших редукторах в соответствии с ответом API.
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchRecommendedPosts } from "../redux/actions/postsActions";
import Post from "../components/sharedComponents/Post";
const RecommendedUserPostsPage = () => {
const dispatch = useDispatch();
const { token } = useSelector((state) => state.auth);
const { data, loading, fetched, error } = useSelector((state) => state.posts.recommendedPosts);
useEffect(() => {
dispatch(fetchRecommendedPosts({ token }));
}, [token]);
return (
<div style={{ margin: "5em" }}>
{fetched && data.map((post) => <Post postData={post} />)}
{error && <p>Oh no!</p>}
{loading && <p>Please stay seated...</p>}
</div>
);
};
export default RecommendedUserPostsPage;
Однако в последнее время все больше людей говорят о «Как избежать логической ловушки». Я еще не использовал это, но мне нравится идея.
Вместо того, чтобы иметь несколько логических свойств, которые необходимо декодировать в вашем контейнере, вы добавляете только эти свойства: data
, error
и state
.
- Свойство
data
содержит данные вашего ответа API. - Свойство
error
будет содержать ошибку / проблему, возникшую во время запроса. - Свойство
state
содержит перечисление (строка / число), которое представляет текущее состояние (очевидно) запроса / ответа.
В вашем контейнере вы можете протестировать свойство state
без необходимости комбинировать дополнительные логические свойства.
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { fetchRecommendedPosts } from "../redux/actions/postsActions";
import Post from "../components/sharedComponents/Post";
// this should be in a separate file `./src/enums/RequestState.js`
const RequestState = {
INITIAL: 'initial',
FETCHED: 'fetched',
LOADING: 'loading',
FAILURE: 'failure',
};
const RecommendedUserPostsPage = () => {
const dispatch = useDispatch();
const { token } = useSelector((state) => state.auth);
const { data, state } = useSelector((state) => state.posts.recommendedPosts);
useEffect(() => {
dispatch(fetchRecommendedPosts({ token }));
}, [token]);
return (
<div style={{ margin: "5em" }}>
{state === RequestState.FETCHED && data.map((post) => <Post postData={post} />)}
{state === RequestState.FAILURE && <p>Oh no!</p>}
{state === RequestState.LOADING && <p>Please stay seated...</p>}
</div>
);
};
export default RecommendedUserPostsPage;