开发者问题收集

React:访问我已映射的数组内的对象属性

2021-11-13
2597

我正在尝试制作我的第一个真正的 React 应用程序,并从数据库中提取信息,更新状态以将该信息设置为数组,然后尝试访问数组中对象的属性。

function App() {

  const [students, setStudents] = useState([]);

  function fetchStudentInfo() {
    fetch('https://api.hatchways.io/assessment/students')
      .then(response => {
        return response.json();
      })
      .then(data => {
        const transformedStudentData = data.students.map(studentData => {
          return {
            imgURL: studentData.pic,
            fullName: `${studentData.firstName} ${studentData.lastName}`,
            email: studentData.email,
            company: studentData.company,
            skill: studentData.skill
          }
        });
        setStudents(transformedStudentData);
      });
  }

  fetchStudentInfo();

  return (
    <div> {console.log(students[0].fullName)}
      <h1>Student Assessments</h1>
    </div>
  )

}

export default App;

我知道我不应该使用 console.logging 来记录我试图获取的信息,但我甚至不确定如何使用 React 中的控制台来了解如何访问我的变量。无论如何,我收到“TypeError:无法读取未定义的属性(读取‘fullName’)”错误,并且失败。 我真的想将数组作为属性传递下来以用于我的组件,但我已经删除了代码以尝试为自己简化问题,这就是我遇到的障碍。

1个回答

第一次渲染时,您的 students 状态是一个空数组,因为这是您初始化它的方式。在第一次渲染时,您无法访问第一个索引(因为尚未获取数据或状态未更新),并且您无法访问尚不存在的元素的属性。

因此,您需要一个渲染条件:1)如果 students.length 为零,则返回加载消息(例如)2)否则 map 覆盖您现在知道存在的学生数组,以生成学生姓名列表。

这是一个使用 useEffect 将数组添加到状态的有效示例在模拟您的 API fetch 三秒后。您应该像这样对 fetch 使用 useEffect (使用空的依赖项数组),而不是直接在组件中调用您的函数。

const { useEffect, useState } = React;

const json = '[{ "fullName": "Bob" },{ "fullName": "Karen" },{ "fullName": "Rick" }]';

function mockApi() {
  return new Promise((res, rej) => {
    setTimeout(() => res(json), 3000);
  });
}

function Example({ data }) {

  const [ students, setStudents ] = useState([]);
  
  useEffect(() => {
    function getData() {
      mockApi()
        .then(json => JSON.parse(json))
        .then(data => setStudents(data));
    }
    getData();
  }, []);

  // Initial log will be `[]`
  // Second log will be the updated state stringified
  useEffect(() => {
    console.log(JSON.stringify(students));
  }, [students]);

  // No data, so return the loading message, or spinner
  if (!students.length) return <div>Loading: wait 3 seconds</div>

  // Data! `map` over it to produce the list
  return (
    <ul>
      {students.map(student => {
        return <li>{student.fullName}</li>;
      })}
    </ul>
  );

};

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Andy
2021-11-13