TypeError: не удается прочесть свойство 'name' неопределенного значения при использовании useState и useEffect

Я новичок в использовании useState и useEffect, и я пытаюсь получить пользователей из randomuser api и отобразить их. Я слежу за документацией и вижу, как мои пользователи вошли в консоль.

Что я могу изменить, чтобы он не сообщал мне Невозможно прочитать имя свойства undefined.

Был бы признателен за помощь.

import axios from "axios";
import { Layout, Loading } from "../components";
// import config from '../config.json';

const Overview = () => {
  const [loading, setLoading] = useState(true);
  const [searchQuery, setSearchQuery] = useState("");
  const [devices, setDevices] = useState([]);

  useEffect(() => {
    async function callApi() {
      const response = await axios.get("https://randomuser.me/api/?results=10");
      const devices = response?.data?.results;
      setDevices(devices);
      // const response = await axios.get(`${config.serverAPI}/devices`);
      // const devices = response?.data?.status === 'success' && response?.data?.devices;
      console.log("Devices", devices);

      await localStorage.setItem("devices", JSON.stringify(devices));
      setLoading(false);
    }
    callApi();
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  return (
    <Layout>
      <div className="overview-page-wrapper">
        {loading && <Loading />}
        <h2>Title</h2>
        <div>{devices[0].name.first}</div>
      </div>
    </Layout>
  );
};

export default Overview;
import ReactGA from "react-ga";
import { withRouter } from "react-router";
import Disclaimer from "./Disclaimer";
import Header from "./Header";
import Sidebar from "./Sidebar";

const Layout = ({ children, match }) => {
  ReactGA.pageview(match.url);
  console.log(111, match.url);

  return (
    <div className="page-wrapper">
      <Sidebar />
      <div className="main-section">
        <Header />
        <div className="content"> {children} </div>{" "}
      </div>{" "}
      <Disclaimer />
    </div>
  );
};

export default withRouter(Layout);

person kimo26    schedule 22.06.2020    source источник
comment
убедитесь, что массив устройств не пуст. Вы можете добавить в представление условный рендеринг, например. {devices.length! == 0 && ‹div› {devices [0] .name.first} ‹/div›}   -  person mouthzipper    schedule 22.06.2020
comment
Отвечает ли это на ваш вопрос? Я не могу сопоставить массив объектов, хотя это напечатано в console.log   -  person k.s.    schedule 22.06.2020


Ответы (2)


Проблема в твоем

return (
    <Layout>
      <div className="overview-page-wrapper">
        {loading && <Loading />}
        <h2>Title</h2>
        <div>{devices[0].name.first}</div>
      </div>
    </Layout>
  );

Потому что сначала вызывается метод рендеринга, а затем ваш хук useEffect и до этого времени devices является пустым массивом.

и devices[0] это undefined

и когда вы делаете devices[0].name, вы, по сути, делаете undefined.name

Чтобы преодолеть это, вы должны сделать что-то вроде

return (
    <Layout>
      <div className="overview-page-wrapper">
        {loading && <Loading />}
        <h2>Title</h2>
        {devices.length > 0 && (<div>{devices[0].name.first}</div>)}
      </div>
    </Layout>
  );
person Adeel Imran    schedule 22.06.2020

Вы готовите состояние загрузки, но оно не покрывает всю визуализацию, поэтому при доступе к свойству его еще нет.

Чтобы исправить это, вы можете попробовать следующее:

<div className="overview-page-wrapper">
  {loading ? 
    <div>loading...</div> 
  : 
    <>
      <h2>Title</h2>
      <div>{devices[0].name.first}</div>
    </>
  }
</div>
person Enric    schedule 22.06.2020