简体   繁体   中英

Cant access object value returned from axios in custom hooks

Hi I'm writing code to get JSON with axios in custom hooks and return the value, but I can't access the object property even it was there.

I have been trying to access like item.title or item["title"] and even JSON.parse() but parse() returned cross origin error.

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;

Function where hook is called and I want to access the object:

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;

The actual response from server http://localhost:8000/post/post_5e9cbf07b44c7 is:

{
    "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"
    }
}

The value of console.log(item) in PostDetail.js is:

{
  "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": {}
}

thanks in advance:)

The problem happens when you try to access the returned value because on initial render the value is not available since the effect runs post render cycle and also because the axios request is async.

It will however work if you actually initialize the state to object within your custom hook

Also make sure that you set res.data.item in the state and not res . Post that you can get the value with item.title

SideNotes:

Please ensure that you prefix your custom hooks names with use which actually helps eslint figure out the distinction between custom hook or a function.

Also since you are making an API call based on param id, I advice you to pass that id as a dependency to useEffect in custom hook so that the scenarios where id is changed also work seamlessly

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;

Use it in PostDetail component like

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM