Что я показываю, пока не вернется выборка в React Redux - PullRequest
1 голос
/ 09 июля 2020

У меня вопрос. У меня есть страница внутри моего приложения, которая отправляет действие и ожидает результата (используя хуки useDispatch и useSelector). Я хотел знать, как правильно отображать пустой div, пока я не получу результаты из отправки? Вот что я написал до сих пор:


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);

  useEffect(() => {
    dispatch(fetchRecommendedPosts({ token }));
  }, []);

  const fetchedPosts = useSelector((state) => state.posts.recommendedPosts);

  // this is the place where I wait for the response from the dispatch
  const posts =
    fetchedPosts.length > 0 ? (
      fetchedPosts.map((post) => <Post postData={post} />)
    ) : (
      <div />
    );

  return <div style={{ margin: "5em" }}>{posts}</div>;
};

export default RecommendedUserPostsPage;


1 Ответ

1 голос
/ 09 июля 2020

Мне всегда нравится добавлять свойства 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;
...