在自定义钩子中从axios返回的无法访问对象值

时间:2020-04-21 13:31:04

标签: javascript reactjs axios react-hooks es6-promise

嗨,我正在编写代码以在自定义钩子中使用axios获取JSON并返回该值,但是即使存在,我也无法访问该对象属性。

我一直试图像item.titleitem["title"]甚至JSON.parse()那样访问,但是parse()返回了跨源错误。

customHooks.js

import { useState, useEffect } from "react";
import axios from "axios";

const GetPost = (id) => {
  const [post, setPost] = useState();
  useEffect(() => {
    axios.get(`http://localhost:8000/post/${id}`).then((res) => setPost(res));
  }, []);

  return post;
};

export default GetPost;

调用钩子的函数,我想访问该对象:

import React from "react";
import getPost from "../customHooks/GetPost";

import { Jumbotron, Container } from "react-bootstrap";

const PostDetail = (props) => {
  const item = getPost(props.match.params.id);

  console.log(item); // i can access the object
  console.log(item.title); //TypeError: Cannot read property 'title' of undefined
  return (
    <Jumbotron fluid>
      <Container>
        {/* <h1>{item.title}</h1>
        <p>{item.description}</p> */}
      </Container>
    </Jumbotron>
  );
};

export default PostDetail;

服务器http://localhost:8000/post/post_5e9cbf07b44c7的实际响应是:

{
    "message": "success",
    "item": {
        "post_id": "post_5e9cbf07b44c7",
        "title": "Asperiores.",
        "description": "Porro iure aliquam laborum veniam quis vel. At itaque voluptas voluptas natus eligendi aut facilis.",
        "content": "lorem ipsum",
        "img_url": "https://lorempixel.com/100/100/cats/?61693",
        "created_by": "user_5e9cbf07b48fc",
        "created_at": "2020-04-19 21:13:43",
        "updated_at": "2020-04-19 21:13:43"
    }
}

PostDetail.js中console.log(item)的值为:

{
  "data": {
    "message": "success",
    "item": {
      "post_id": "post_5e9cbf07b44c7",
      "title": "Asperiores.",
      "description": "Porro iure aliquam laborum veniam quis vel. At itaque voluptas voluptas natus eligendi aut facilis.",
      "content": "lorem ipsum.",
      "img_url": "https://lorempixel.com/100/100/cats/?61693",
      "created_by": "user_5e9cbf07b48fc",
      "created_at": "2020-04-19 21:13:43",
      "updated_at": "2020-04-19 21:13:43"
    }
  },
  "status": 200,
  "statusText": "OK",
  "headers": {
    "cache-control": "no-cache, private",
    "content-type": "application/json"
  },
  "config": {
    "url": "http://localhost:8000/post/post_5e9cbf07b44c7",
    "method": "get",
    "headers": {
      "Accept": "application/json, text/plain, */*"
    },
    "transformRequest": [
      null
    ],
    "transformResponse": [
      null
    ],
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1
  },
  "request": {}
}

提前感谢:)

1 个答案:

答案 0 :(得分:2)

当您尝试访问返回的值时会发生问题,因为在初始渲染时该值不可用,因为该效果在渲染周期后运行,而且因为axios请求是异步的。

但是,如果您实际上将状态初始化为自定义钩子中的对象,它将起作用

还要确保您将res.data.item设置为状态,而不是res。发布您可以使用item.title

获取值

旁注:

请确保为自定义钩子名称加上use前缀,这实际上有助于确定自定义钩子或函数之间的区别。

另外,由于您基于参数id进行API调用,因此我建议您将该ID作为依赖传递给自定义钩子中的useEffect,以便ID更改的场景也可以无缝工作

import { useState, useEffect } from "react";
import axios from "axios";

const useGetPost = (id) => {
  const [post, setPost] = useState({}); // initialize here
  useEffect(() => {
    axios.get(`http://localhost:8000/post/${id}`).then((res) => setPost(res.data.item));
  }, [id]); // pass id as a dependency here

  return post;
};

export default useGetPost;

在PostDetail组件中使用它,例如

import React from "react";
import useGetPost from "../customHooks/GetPost";

import { Jumbotron, Container } from "react-bootstrap";

const PostDetail = (props) => {
  const item = useGetPost(props.match.params.id);

  console.log(item); 
  console.log(item.title);
  return (
    <Jumbotron fluid>
      <Container>
        {/* <h1>{item.title}</h1>
        <p>{item.description}</p> */}
      </Container>
    </Jumbotron>
  );
};

export default PostDetail;