1

I have implemented fetch and set it into object. However, when I want to get its value. It shows undefined, I have no idea about this. Here is the code.

import {useEffect,useState} from 'react';
import { useRouter, Router } from 'next/router';
import Layout from '../../components/MyLayout';
import Settings from '../../components/Settings';

const Post = (props) => {

  const [object, setObject] = useState({});
  const router = useRouter();

  useEffect(
    () => {
      const data = router.query;
      const FormData = new URLSearchParams();
      FormData.append('slug',data.id);
      fetch(Settings.api+'viewPost',{
        method: 'POST',
        body: FormData
      })
        .then(res=>res.json())
        .catch(function(e){
            console.log(e)}
        )
        .then(obj=>{
            setObject(obj.data[0])
        })
    }
    , [router.query]
  )
  return (
    <Layout>
     <h1>{object.title}</h1> --> I would like to display here
    </Layout>
  );
}

export default Post;

Anyway here is the json I would like to implement

{
  "page": 1,
  "total": 0,
  "data": [
    {
      "postId": 4,
      "boardId": "",
      "username": "[email protected]",
      "title": "How To Make Money",
      "slug": "how-to-make-money",
      "answer": 0,
      "checked": 0,
      "status": "",
      "waktu": "2019-10-16 04:45:30"
    }
  ]
}

Here is the error

TypeError: Cannot read property 'title' of undefined

I really appreciate any answer. Thank you.

0

3 Answers 3

3

Try just logging console.log(object), You already set the value of the object state as whatever obj.data[0] was.

EDIT: You can probably get away with doing a check before the useEffect gets triggered:

if (!object) {
  return <h1>Loading...</h1>
}

console.log(object.data[0])
return (
    <Layout>
      <h1>{router.query.id}</h1>
    </Layout>
  );
Sign up to request clarification or add additional context in comments.

9 Comments

console.log(object) works fine. However, I would like to get value inside its object. It can only works at "object.data". If I go further than that, it does not works ex (object.data[0]). Anyway, I just added json output to help you understand more. Thank you anyway
I see it. I was confused by the comment. When you log it does it get logged twice?
That is a problem during initial render. object = {}.
Right. UseEffect will trigger after the mount so the initial value will be {}, but it should set the new value.
Maybe you need to do a check before the return if (!data) return <h1>Loading...</h1>
|
2
import {useEffect,useState} from 'react';
import { useRouter, Router } from 'next/router';
import Layout from '../../components/MyLayout';
import Settings from '../../components/Settings';

const Post = (props) => {

const [object, setObject] = useState({});
const router = useRouter();

useEffect(
   () => {
     const data = router.query;
     const FormData = new URLSearchParams();
     FormData.append('slug',data.id);
     fetch(Settings.api+'viewPost',{
       method: 'POST',
       body: FormData
     })
     .then(res=>res.json())
     .catch(function(e){
         console.log(e)}
     )
     .then(obj=>{
         setObject(obj.data[0])
     })
 }
, [router.query]
)
//console.log(object.data[0]); --> does not work here
return (
  <Layout>
    <h1>{router.query.id}</h1>
  </Layout>
);
} 

export default Post; 

1 Comment

Thanks, it works. But whats the different to set 'obj' directly instead of 'obj.data[0]'. Does it not support multiple nested JSON?
1

This might the problem when it is getting rendered initially. Before the api call it might not have data.

You need to check it before using that

{ object && object.data[0]}

or you can show loading when you dont have data

if (!data) return <span>Loading...</span>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.