I am trying to display data in react but i get Cannot read properties of undefined (reading 'map')

huangapple go评论83阅读模式
英文:

I am trying to display data in react but i get Cannot read properties of undefined (reading 'map')

问题

这个错误是因为在组件渲染时,backendData 变量还是 undefined,导致无法对其使用 map 函数。这可能是因为异步请求未完成时组件已经渲染了。

为了解决这个问题,你可以在渲染之前添加一个条件,确保 backendData 有数据再执行 map。例如:

{backendData && backendData.map(child => {
  // 渲染表格内容
})}

这样,只有在 backendData 有值的情况下才会执行 map,避免了在数据未准备好时出现错误。

英文:

I receive data in react using axios but when i try to map through it i get an error "Cannot read properties of undefined (reading 'map')" I was trying to find solutions to this and i think that react first renders the page before setting the data, I also tried looping thorugh the data manually or using forEach but still got a variation of the errors below.
For some reason it also returns 3 similar errors every time it runs

Code:

import axios from "axios";

function Table() {

let [backendData, setData] = useState();


async function getData(){
  await axios.get("table")
  .then(response => response.data)
  .then(data => setData(data))
}

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





return(
  <div>
    <table>
      <thead>
        <tr>
          <th>Child's Name</th>
          <th>Child's Age</th>
          <th>Room No.</th>
          <th>Parent/Guardian Location</th>
          <th>Parent/Guardian Signature In</th>
          <th>Staff Signature In</th>
          <th>Parent/Guardian Signature Out</th>
          <th>Staff Signature Out</th>
        </tr>
      </thead>

            {backendData.map(child => {
              <tr key={child._id}>
                <td>{child.childName}</td>
                <td>{child.childAge}</td>
                <td>{child.roomNumber}</td>
                <td>temporary</td>
                <td><img src={child.parentSignature} /></td>
                <td><img src={child.parentSignature} /></td>
                <td><img src={child.parentSignature} /></td>
                <td><img src={child.parentSignature} /></td>
              </tr> 
            })}

    </table>
  </div>
  ) 

}

export default Table;

Error:

Cannot read properties of undefined (reading 'map')
TypeError: Cannot read properties of undefined (reading 'map')
   at Table (http://localhost:3000/static/js/bundle.js:2183:29)
   at renderWithHooks (http://localhost:3000/static/js/bundle.js:24189:22)
   at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:27475:17)
   at beginWork (http://localhost:3000/static/js/bundle.js:28771:20)
   at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:13781:18)
   at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:13825:20)
   at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:13882:35)
   at beginWork$1 (http://localhost:3000/static/js/bundle.js:33756:11)
   at performUnitOfWork (http://localhost:3000/static/js/bundle.js:33003:16)
   at workLoopSync (http://localhost:3000/static/js/bundle.js:32926:9)
ERROR
Cannot read properties of undefined (reading 'map')
TypeError: Cannot read properties of undefined (reading 'map')
   at Table (http://localhost:3000/static/js/bundle.js:2183:29)
   at renderWithHooks (http://localhost:3000/static/js/bundle.js:24189:22)
   at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:27475:17)
   at beginWork (http://localhost:3000/static/js/bundle.js:28771:20)
   at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:13781:18)
   at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:13825:20)
   at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:13882:35)
   at beginWork$1 (http://localhost:3000/static/js/bundle.js:33756:11)
   at performUnitOfWork (http://localhost:3000/static/js/bundle.js:33003:16)
   at workLoopSync (http://localhost:3000/static/js/bundle.js:32926:9)
ERROR
Cannot read properties of undefined (reading 'map')
TypeError: Cannot read properties of undefined (reading 'map')
   at Table (http://localhost:3000/static/js/bundle.js:2183:29)
   at renderWithHooks (http://localhost:3000/static/js/bundle.js:24189:22)
   at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:27475:17)
   at beginWork (http://localhost:3000/static/js/bundle.js:28771:20)
   at beginWork$1 (http://localhost:3000/static/js/bundle.js:33734:18)
   at performUnitOfWork (http://localhost:3000/static/js/bundle.js:33003:16)
   at workLoopSync (http://localhost:3000/static/js/bundle.js:32926:9)
   at renderRootSync (http://localhost:3000/static/js/bundle.js:32899:11)
   at recoverFromConcurrentError (http://localhost:3000/static/js/bundle.js:32391:24)
   at performConcurrentWorkOnRoot (http://localhost:3000/static/js/bundle.js:32303:26)```


</details>


# 答案1
**得分**: 1

这是因为你的 `backendData` 变量具有未定义的初始值。React 的 `useState()` 钩子接受一个参数,该参数将被设置为状态变量的初始值。

目前在你的代码中,你的 React 组件将尝试在 `useEffect` 完成 axios 请求之前返回 JSX。由于你没有传递一个初始值给你的 `useState()` 钩子,所以你的 `backendData` 变量最初具有未定义的值。当尝试访问你将在数组上使用的 `.map()` 函数时,对于未定义的数据类型,不存在这样的方法。

相反,可以这样做:
```Javascript
const [backendData, setData] = useState([]);

这将把 backendData 的初始值设置为空数组。现在,当你的 backendData.map() 函数运行时,不会出现错误,因为现在有一个空数组可以进行映射。

英文:

This is happening because your backendData variable has an initial value of undefined. React useState() hook accepts a parameter, which will be set as the initial value for the state variable.

Currently in your code, your react component will attempt to return your jsx even before your useEffect finishes your axios request. Since you aren't passing an initial value to your useState() hook, your backendData variable has an undefined value initially. And when trying to access the .map() function that you would use on an array, there is no such method that exists for your undefined data type.

Instead, do

const [backendData, setData] = useState([]);

This'll set the initial value of backendData to an empty array. And when your backendData.map() function runs now, there will be no error because there is now an empty array to map over.

答案2

得分: 1

这是因为在JSX中下面的代码(map)在API的响应之前运行。因此,您可以通过在map之前加入?来解决这个问题。像这样:

{backendData?.map(child => (
  <tr key={child._id}>
    <td>{child.childName}</td>
    <td>{child.childAge}</td>
    <td>{child.roomNumber}</td>
    <td>temporary</td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
  </tr>
))}

或者

{backendData?.length > 0 && backendData.map(child => (
  <tr key={child._id}>
    <td>{child.childName}</td>
    <td>{child.childAge}</td>
    <td>{child.roomNumber}</td>
    <td>temporary</td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
  </tr>
))}
英文:

This is because the below code (map )in JSX runs before the response of API. So you can resolve it by putting ? before map. Like this

 {backendData?.map(child =&gt; {
          &lt;tr key={child._id}&gt;
            &lt;td&gt;{child.childName}&lt;/td&gt;
            &lt;td&gt;{child.childAge}&lt;/td&gt;
            &lt;td&gt;{child.roomNumber}&lt;/td&gt;
            &lt;td&gt;temporary&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
          &lt;/tr&gt; 
        })}

OR

 {backendData?.length &gt; 0 &amp;&amp; backendData.map(child =&gt; {
          &lt;tr key={child._id}&gt;
            &lt;td&gt;{child.childName}&lt;/td&gt;
            &lt;td&gt;{child.childAge}&lt;/td&gt;
            &lt;td&gt;{child.roomNumber}&lt;/td&gt;
            &lt;td&gt;temporary&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
            &lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
          &lt;/tr&gt; 
        })}

答案3

得分: 1

On the first render, the effect has not run yet, so backendData is the initial value passed to useState: undefined, in this case.

The component tries to call map on undefined, which causes the error.

To fix this, you could set the initial state to an empty array

const [backendData, setData] = useState([]);

or use optional chaining to avoid calling map and immediately return undefined when backendData is undefined. Note that you should not use curly braces in order to directly return the JSX from map.

{backendData?.map(child => (
  <tr key={child._id}>
    <td>{child.childName}</td>
    <td>{child.childAge}</td>
    <td>{child.roomNumber}</td>
    <td>temporary</td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
    <td><img src={child.parentSignature} /></td>
  </tr>
))}
英文:

On the first render, the effect has not run yet, so backendData is the inital value passed to useState: undefined, in this case.

The component tries to call map on undefined, which causes the error.

To fix this, you could set the initial state to an empty array

const [backendData, setData] = useState([]);

or use optional chaining to avoid calling map and immediately return undefined when backendData is undefined. Note that you should not use curly braces in order to directly return the JSX from map.

{backendData?.map(child =&gt; (
  &lt;tr key={child._id}&gt;
	&lt;td&gt;{child.childName}&lt;/td&gt;
	&lt;td&gt;{child.childAge}&lt;/td&gt;
	&lt;td&gt;{child.roomNumber}&lt;/td&gt;
	&lt;td&gt;temporary&lt;/td&gt;
	&lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
	&lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
	&lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
	&lt;td&gt;&lt;img src={child.parentSignature} /&gt;&lt;/td&gt;
  &lt;/tr&gt; 
))}

答案4

得分: 1

当使用“map”方法渲染您的backendData状态时,您假设正在遍历一个数组列表。但您声明了一个初始值为undefined的状态。

解决此问题的简单方法是将状态重新声明如下:

const [backendData, setData] = useState([]);

而不是:

let [backendData, setData] = useState();
英文:

When rendering your backendData state with the "map" method you're assuming you're reading through an array or a list. But you're declaring a state with an initial value of undefined.

An easy fix to this issue would be redeclaring your state as follows:

const [backendData, setData] = useState([]);

Instead of:

let [backendData, setData] = useState();

huangapple
  • 本文由 发表于 2023年8月5日 00:12:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76837609.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定