簡體   English   中英

反應:未捕獲的類型錯誤:無法讀取未定義的屬性

[英]React: Uncaught TypeError: Cannot read properties of undefined

這個問題已經解決了。 向下滾動或單擊此處查看解決方案

我正在嘗試使用 React 從我的服務器中提取 JSON 數據並使用兩個函數渲染它。 但似乎這兩個渲染函數無法正確讀取 json 中的值。 我確定我的數據服務器工作正常。

錯誤日志:

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)

應用組件:

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>
    )
}

問題組件:

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;

JSON 數據:

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

我認為它們不是純函數,它們是組件,你不能共享全局變量,這不是在 React 中的組件之間傳遞數據的方式,正確的方法是使用上下文或道具,通過道具我離開您是以下方式的示例,您也應該將其應用於其他變量,例如:

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;

首先,在App中刪除JSON.parse(resJson)因為它已經被res.json()解析了。 在獲取數據時使用一些加載器,因為它是異步發生的,並且您的組件首先呈現。 為此,不要將useState作為參數,因此item在開始時是undefined的。

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>
    )
}

其次,在使用 React 時,您不應該使用全局變量來渲染組件中的數據,而是使用propsstate 為此,請更改Question組件,使其接收所需的數據作為props ,並注意它已在App中傳遞給它:

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>
    )
}

編輯:我終於解決了這個問題。 希望它會幫助你。

前端和后端有幾個問題。

前端:

  1. 我使用useStateuseEffect來處理獲取的數據。 這是我的代碼:
const [item, setItems] = useState()

    useEffect(() => {
        fetch('http://localhost:61780/')
            .then((res) => res.json())
            .then((data) => {
                setItems(data)
            })
    }, []);
  1. 在讀取 json 數據時,請執行以下操作: <level 1>?.<level 2>?.<level 3>

不要這樣做: <level 1>.<level 2>.<level 3> 這將拋出一個異常: Cannot read... from type 'undefined'

示例代碼:

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 數據:

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

后端:

  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 *>

如果你不這樣做,它會拋出一個異常: CORS header 'Access-Control-Allow-Origin' missing 不知道其他js是不是這樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM