0

Not sure why I'm getting TypeError: project.Item is not a functionerror when I try to access an object inside of an array returned on my GET request. This is how my code looks. The weird thing about this is that sometimes I get no error with this exact same code.

   const getProjects = async() => {
  var myHeaders = new Headers();
  myHeaders.set('Authorization', 'Basic ' + credentials);

  var requestOptions = {
    method: 'GET',
    headers: myHeaders,
    redirect: 'follow'
  };

  let response;

    try {
        response = await fetch (`${APIlink}/projects/`+ props.match.params.project_uid, requestOptions)
    } catch (err) {
        return;
    }
    const result = await response.json();
    setproject(result);
  }
  console.warn("props", props);
  console.log(project);
  

  useEffect(() => {
    getProjects();
  }, []);


  return (<div>
      <Header />
      <img src={logo}/>
  <h1>Project Title</h1>
    <Row style = {{display: "flex"}}><Col xs="6">{project.Item.profName}</Col>
                 <Col xs="6">{project.Item.dept}</Col>
    </Row>
    <Row style = {{display: "flex"}}><Col xs="6">{project.Item.duration} months</Col>
                 <Col xs="6">INR {project.Item.stipend}</Col>
    </Row>
    <Row style = {{displey: "flex"}}><Col xs="6">{project.Item.totalSlots}</Col>
                 <Col xs="6">Start Date</Col>
    </Row>
    {project.Item.description}
    <br></br>
    {project.Item.responsibilities}
    <br></br>
    

  </div>);

The following object is returned when I make a GET request to get the details of a particular Project

{
  "Item": {
    "project-uid": "e50ffdfaad1c4de31d6ad5e82d789c6a",
    "responsibilities": "he standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from de Finibus Bonorum et Malorum by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham",
    "preReq": "Fourth year",
    "addDetails": "The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from de Finibus Bonorum et Malorum by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham",
    "dept": "mechanical",
    "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.",
    "duration": "12",
    "totalSlots": "5",
    "stipend": "10000",
    "profName": "Dr. Aaron Sorkin",
    "user-uid": "7e7199247de1125a6dc1518dd78ba554"
  }
}
5
  • 1
    Item.map doesn't appear anywhere in the code you show. I don't think the error is coming from this part. But otherwise, if you do use Item.map anywhere, the issue is that it's an object, not an array. Commented May 22, 2021 at 18:09
  • I've edited my question, the error is project.Item Commented May 22, 2021 at 18:11
  • 1
    you should add a condition to your return to check if project is initialised before rendering like return project && (<div> ...) Commented May 22, 2021 at 18:14
  • Thanks It worked! Can you explain the reason behind it? Commented May 22, 2021 at 18:21
  • 1
    project && ( ... ) will still fail if the initialState of the project is an { } . Commented May 22, 2021 at 18:26

1 Answer 1

1

Your useEffect will get called after the component is mounted . So if your initial state of project is null or {} . you will get an error . You can add an additional state called loading which you can set to false once the API call is successful . Adding a loading state is a good practice when making api calls . So that we can render a loader in the future which is a good UX .

const [ loading, setLoading ] = useState(true);

const getProjects = async() => {
  var myHeaders = new Headers();
  myHeaders.set('Authorization', 'Basic ' + credentials);

  var requestOptions = {
    method: 'GET',
    headers: myHeaders,
    redirect: 'follow'
  };
 
  let response;

    try {
        response = await fetch (`${APIlink}/projects/`+ props.match.params.project_uid, requestOptions)
    } catch (err) {
        return;
    } finally{
      setLoading(false);
     }
    const result = await response.json();
    setproject(result);
  }
  console.warn("props", props);
  console.log(project);
  

  useEffect(() => {
    getProjects();
  }, []);

  if(loading)
    return <h1> Fetching Data ...</h1>

  return (<div>
      <Header />
      <img src={logo}/>
  <h1>Project Title</h1>
    <Row style = {{display: "flex"}}><Col xs="6">{project?.Item?.profName || ''}</Col>
                 <Col xs="6">{project?.Item?.dept || ''}</Col>
    </Row>
    <Row style = {{display: "flex"}}><Col xs="6">{project?.Item?.duration || ''} months</Col>
                 <Col xs="6">INR {project?.Item?.stipend || ''}</Col>
    </Row>
    <Row style = {{displey: "flex"}}><Col xs="6">{project?.Item?.totalSlots || ''}</Col>
                 <Col xs="6">Start Date</Col>
    </Row>
    {project?.Item?.description || ''}
    <br></br>
    {project?.Item?.responsibilities || ''}
    <br></br>
    

  </div>);
Sign up to request clarification or add additional context in comments.

2 Comments

Edited the answer to use optional chaining - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Thank you! I will design a loading component too :)

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.