反应组件状态和API提取

时间:2019-06-22 09:28:33

标签: reactjs

我过去几天一直在研究React。在我的博客项目中,我正在使用Axios从API获取数据。这是我的组件:

import React, { useState, useEffect } from "react";
import axios from "axios";
import { apiConstants } from "../../constants";
import SinglePost from "./SinglePost";

const PostContent = props => {
  const {
    match: { params }
  } = props;
  const [post, setPost] = useState({});

  useEffect(() => {
    axios
      .get(apiConstants.singlePost + `${params.post_slug}`)
      .then(function(response) {
        setPost(response.data);
      })
      .finally(function() {
        // always executed
      });
  }, []);

  return (
    <React.Fragment>
      <div className="container">
        <div className="row">
          <div className="col-lg-8 col-md-10 mx-auto">
            <SinglePost post={post} />
          </div>
        </div>
      </div>
    </React.Fragment>
  );
};

export default PostContent;

上面的代码运行良好,尽管我第一次注意到它尝试使用空({})的post对象渲染组件(由于'useState'中的默认值)。但是,这会导致我的子组件出现问题,因为它直接使用了“ post”对象属性。例如:“ post.content”。这是我的“ SinglePost”组件的代码:

const SinglePost = props => {
  const { post } = props;
  console.log(post);
  return (
      <div>{post.content}</div>
  );
};

它为{post.content}对象返回未定义的错误。要解决此问题,我必须使用类似{post && <SinglePost post={post} />}的方法,但是感觉不对。有没有更好的方法来处理这种情况。

3 个答案:

答案 0 :(得分:0)

考虑修改PostContent组件的呈现逻辑,以解决在网络请求期间不存在发布数据的情况。

例如,您可以将post状态初始化为null,然后更新渲染的结果以防止SinglePost为{{1 }}。

一旦完成网络请求并设置了post状态,该组件将重新渲染,从而使null处于非空post状态:

SinglePost

这种方法通常是异步请求和呈现的最简单且更常见的模式。

您可能还需要考虑其他一些方法,例如这种declarative approach to data fetching或使用Reacts suspense feature for asynchronous rendering

答案 1 :(得分:0)

您需要将帖子的初始值设置为数组:

import React, { useState, useEffect } from "react";
import axios from "axios";
import { apiConstants } from "../../constants";
import SinglePost from "./SinglePost";

const PostContent = props => {
  const {
    match: { params }
  } = props;
  const [post, setPost] = useState([]);

  useEffect(() => {
    axios
      .get(apiConstants.singlePost + `${params.post_slug}`)
      .then(function(response) {
        setPost(response.data);
      })
      .finally(function() {
        // always executed
      });
  }, []);

  return (
    <React.Fragment>
      <div className="container">
        <div className="row">
          <div className="col-lg-8 col-md-10 mx-auto">
            <SinglePost post={post} />
          </div>
        </div>
      </div>
    </React.Fragment>
  );
};

export default PostContent;

并通过数组在单个帖子图中

const SinglePost = props => {
  const { post } = props;
  console.log(post);
  return (
    <div>
      {post.map((post, key) => (
        <div key={key}>{post.content}</div>
      ))}
    </div>
  );
};

答案 2 :(得分:0)

您可以做类似的事情

import React, { useState, useEffect } from "react";
import axios from "axios";
import { apiConstants } from "../../constants";
import SinglePost from "./SinglePost";

const PostContent = props => {
  const {
    match: { params }
  } = props;
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    axios
      .get(apiConstants.singlePost + `${params.post_slug}`)
      .then(function(response) {
        setPosts(response.data);
      })
      .finally(function() {
        // always executed
      });
  }, []);

  return (
    <React.Fragment>
      <div className="container">
        <div className="row">
          <div className="col-lg-8 col-md-10 mx-auto">
            {this.state.posts.map(post => (<SinglePost post={post} key={post.id} />))

          </div>
        </div>
      </div>
    </React.Fragment>
  );
};

export default PostContent;