admin管理员组

文章数量:1334887

THIS QUESTION IS ALREADY SOLVED. Scroll down or click here to view solutions

I am trying to use React to extract a JSON data from my server and render it with two functions. But it seems that the two render functions cannot read the values in the json correctly. I'm sure that my data server is working correctly.

Error log:

Unhandled Runtime Error
Uncaught TypeError: Cannot read properties of undefined (reading 'title')

Source
http://localhost:8080/dist/App.js [:19:68]
TypeError: Cannot read properties of undefined (reading 'title')
    at Question (http://localhost:8080/dist/App.js:19:68)
    at renderWithHooks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:16313:18)
    at mountIndeterminateComponent (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:20077:13)
    at beginWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:21590:16)
    at beginWork$1 (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:27414:14)
    at performUnitOfWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26548:12)
    at workLoopSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26454:5)
    at renderRootSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26422:7)
    at performSyncWorkOnRoot (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26074:20)
    at flushSyncCallbacks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:12050:22)

App ponent:

let prop

function App() {
    const [item, setItems] = useState([])

    useEffect(() => {
        fetch('http://localhost:9090/')
            .then((res) => res.json())
            .then((resJson) => {
                const data = JSON.parse(resJson)
                setItems(data)
            })
    }, [])
    prop = item
    return (
        <div>
            <Question/>
            <hr/>
        </div>
    )
}

Question ponent:

function Question() {
    return (
        <div className={"question"}>
            <h1>{ prop.question.title }</h1>
            <p className={"info"}>Created by user: { prop.question.create_by }</p><br/>
            <p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(prop.question.time)) }</p><br/>
            <hr/>
            <div dangerouslySetInnerHTML={{__html: prop.question.detail}}></div>
        </div>
    )
}

export default App;

The JSON data:

{
  "question": {
    "title": "Question",
    "create_by": "AZ",
    "time": 1661394765044,
    "detail": "<h4>info</h4>"
  },
  "answers": [
    {
      "create_by": "baa",
      "time": 1661394765044,
      "detail": "<h4>abc</h4>"
    }
  ]
}

THIS QUESTION IS ALREADY SOLVED. Scroll down or click here to view solutions

I am trying to use React to extract a JSON data from my server and render it with two functions. But it seems that the two render functions cannot read the values in the json correctly. I'm sure that my data server is working correctly.

Error log:

Unhandled Runtime Error
Uncaught TypeError: Cannot read properties of undefined (reading 'title')

Source
http://localhost:8080/dist/App.js [:19:68]
TypeError: Cannot read properties of undefined (reading 'title')
    at Question (http://localhost:8080/dist/App.js:19:68)
    at renderWithHooks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:16313:18)
    at mountIndeterminateComponent (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:20077:13)
    at beginWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:21590:16)
    at beginWork$1 (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:27414:14)
    at performUnitOfWork (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26548:12)
    at workLoopSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26454:5)
    at renderRootSync (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26422:7)
    at performSyncWorkOnRoot (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:26074:20)
    at flushSyncCallbacks (http://localhost:8080/_snowpack/pkg/react-dom.v18.2.0.js:12050:22)

App ponent:

let prop

function App() {
    const [item, setItems] = useState([])

    useEffect(() => {
        fetch('http://localhost:9090/')
            .then((res) => res.json())
            .then((resJson) => {
                const data = JSON.parse(resJson)
                setItems(data)
            })
    }, [])
    prop = item
    return (
        <div>
            <Question/>
            <hr/>
        </div>
    )
}

Question ponent:

function Question() {
    return (
        <div className={"question"}>
            <h1>{ prop.question.title }</h1>
            <p className={"info"}>Created by user: { prop.question.create_by }</p><br/>
            <p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(prop.question.time)) }</p><br/>
            <hr/>
            <div dangerouslySetInnerHTML={{__html: prop.question.detail}}></div>
        </div>
    )
}

export default App;

The JSON data:

{
  "question": {
    "title": "Question",
    "create_by": "AZ",
    "time": 1661394765044,
    "detail": "<h4>info</h4>"
  },
  "answers": [
    {
      "create_by": "baa",
      "time": 1661394765044,
      "detail": "<h4>abc</h4>"
    }
  ]
}
Share Improve this question edited Aug 29, 2022 at 9:17 Arthur Zhou asked Aug 25, 2022 at 23:45 Arthur ZhouArthur Zhou 531 gold badge2 silver badges4 bronze badges 5
  • Hi Arthur, did you try out the answer I pasted. – Youssouf Oumar Commented Aug 27, 2022 at 8:45
  • ofcourse, and there's still some error. And im checking my backend. – Arthur Zhou Commented Aug 27, 2022 at 10:27
  • A different one? – Youssouf Oumar Commented Aug 27, 2022 at 10:29
  • thanks, but im planning to use other js. Because even the example from their official doc went wrong. Thanks for your answers :) – Arthur Zhou Commented Aug 27, 2022 at 10:32
  • Hi Arthur, you should be pasting an answer instead of editing the question itself. It's how QA should be here in Stack Overflow :) – Youssouf Oumar Commented Aug 28, 2022 at 18:38
Add a ment  | 

3 Answers 3

Reset to default 0

I think they are not pure functions, they are ponents, you cannot share global variables and that is not the way to pass data between ponents in React, the way to do it correctly is using a context or props, to pass through props I leave you an example of the following way, you should apply this in the other variables too, example:

function App() {
    const [item, setItems] = useState([])

    useEffect(() => {
        fetch('http://localhost:9090/')
            .then((res) => res.json())
            .then((resJson) => {
                const data = JSON.parse(resJson)
                setItems(data)
            })
    }, [])

    return (
        <div>
            <Question title={item.question.title}/>
            <hr/>
        </div>
    )
}

function Question({title}) {
    return (
        <div className={"question"}>
            <h1>{ title }</h1>
            <p className={"info"}>Created by user: { prop.question.create_by }</p><br/>
            <p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(prop.question.time)) }</p><br/>
            <hr/>
            <div dangerouslySetInnerHTML={{__html: prop.question.detail}}></div>
        </div>
    )
}

export default App;

First, in App remove JSON.parse(resJson) as it's already parsed by res.json(). Use some loader while fetching the data as it happens asynchronously, and your ponent render first. For that give nothing to useState as parameter so item is undefined at the beginning.

function App() {
    const [item, setItems] = useState()

    useEffect(() => {
        fetch('http://localhost:9090/')
            .then((res) => res.json())
            .then((data) => {
                setItems(data)
            })
    }, []);

    if(!item) return <p>Fetching data...</p>

    return (
        <div>
            <Question question = {item.question}/>
            <hr/>
        </div>
    )
}

Second, you shouldn't be using global variables to render data in your ponents when using React, instead use props and state. To do so, change Question ponent so it receives the data it needs as props and notice it's passed in App to it:

function Question(props) {
    return (
        <div className={"question"}>
            <h1>{ props.question.title }</h1>
            <p className={"info"}>Created by user: { props.question.create_by }</p><br/>
            <p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(props.question.time)) }</p><br/>
            <hr/>
            <div dangerouslySetInnerHTML={{__html: props.question.detail}}></div>
        </div>
    )
}

EDIT: I finally solved this problem. Hope it will help you.

There are several problems on frontend and backend.

Frontend:

  1. I use useState and useEffect to hendle fetched data. This is my code:
const [item, setItems] = useState()

    useEffect(() => {
        fetch('http://localhost:61780/')
            .then((res) => res.json())
            .then((data) => {
                setItems(data)
            })
    }, []);
  1. While reading the json data, do like this: <level 1>?.<level 2>?.<level 3>.

DON'T DO THIS: <level 1>.<level 2>.<level 3>. This will throw out an exception: Cannot read ... from type 'undefined'

Example code:

import React, {useEffect, useState} from 'react';
import './extraUI.css'


function App() {
    const [item, setItems] = useState()

    useEffect(() => {
        fetch('http://localhost:61780/')
            .then((res) => res.json())
            .then((data) => {
                setItems(data)
            })
    }, []);
    console.warn(item)

    return (
        <>
            <Question props={item}/>
            <hr/>
            <Answer props={item}/>
        </>
    )
}

function Question({props}) {
    return (
        <div className={"question"}>
            <h1>{ props?.question?.title }</h1>
            <p className={"info"}>Created by user: { props?.question?.create_by }</p><br/>
            <p className={"info"}>On { }</p><br/>
            <hr/>
            <div dangerouslySetInnerHTML={{__html: props?.question?.detail}}></div>
        </div>
    )
}

function Answer({props}) {
    return (
        props?.answers?.map((answer) => {
            return (
                <div className={"answer"}>
                    <h4 className={"info"}>Answer by: { answer?.create_by }</h4><br/>
                    <p className={"info"}>On { Intl.DateTimeFormat('en-US', {year: 'numeric', month: '2-digit',day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit'}).format(new Date(answer?.time)) }</p><br/>
                    <hr/>
                    <div dangerouslySetInnerHTML={{__html: answer?.detail}}></div>
                </div>
            )
        })
    )
}

export default App;

Json data:

{
  "question": {
    "title": "Question",
    "create_by": "AZ",
    "time": 1661394765044,
    "detail": "<h4>info</h4>"
  },
  "answers": [
    {
      "create_by": "baa",
      "time": 1661394765044,
      "detail": "<h4>abc</h4>"
    }
  ]
}

Backend:

  1. You need to add a header in your server responce: Access-Control-Allow-Origin, and it's value is your api url(or you can use * if your api is a public one) It's like this: Access-Control-Allow-Origin: <url or *>

If you don't do this, it will throw out an exception: CORS header 'Access-Control-Allow-Origin' missing. I'm not sure if other js is like this.

本文标签: javascriptReact Uncaught TypeError Cannot read properties of undefinedStack Overflow