无法读取未定义的属性...上下文中的属性/值

问题描述

我从UserDetails.js中遇到错误“无法读取未定义的属性'名称'”。该“名称”值来自上下文。

这是我的代码

UsersContext.js:

import React,{ createContext,useState,useEffect } from 'react'
import Axios from 'axios';

export const UserContext = createContext()

export function UserProvider(props) {

    const [users,setUsers] = useState([]);
    const [loading,setLoading] = useState(false);
    const [error,setError] = useState(false);

    useEffect(() => {
        const getNews = async () => {
            setLoading(true);
            try {
                const req = await Axios.get(`https://jsonplaceholder.typicode.com/users`);
                const data = req.data;

                setUsers(c => {
                    return [
                        ...data
                    ]
                })

                if(data.status !== "ok") throw new Error('error from api server');

            } catch (error) {
                setError(true)
            }
            setLoading(false);
        }

        getNews();
    },[])

    return (
        <UserContext.Provider value={{users,loading,error}}>
            {props.children}
        </UserContext.Provider>
    )
}

UserDetails.js:

import React,{ useContext } from 'react'
import { UserContext } from '../contexts/UsersContext'

function UserDetails(props) {
    const {users} = useContext(UserContext)

    return (
        <div className="card">
            <div className="card-header">
                {users[0].name}
            </div>
        </div>
    )
}

export default UserDetails
来自UserDetail的

{users [0] .name}未定义,但是当我尝试使用{JSON.stringify(users [0])}时,它具有值:

{"id":1,"name":"Leanne Graham","username":"Bret","email":"Sincere@april.biz","address":{"street":"Kulas Light","suite":"Apt. 556","city":"Gwenborough","zipcode":"92998-3874","geo":{"lat":"-37.3159","lng":"81.1496"}},"phone":"1-770-736-8031 x56442","website":"hildegard.org","company":{"name":"Romaguera-Crona","catchPhrase":"multi-layered client-server neural-net","bs":"harness real-time e-markets"}}

但是为什么在使用JSON.stringify时有一个值,但是没有JSON.stringify时没有值(未定义)?

解决方法

这是因为请求尚未返回结果,并且用户仍然是[], 因此,要解决问题,您应该执行以下操作:

return loading? null : (
    <div className="card">
        <div className="card-header">
            {users[0].name}
        </div>
    </div>
)
,

这是因为 useEffect 挂钩中的请求是异步的,并且在首次渲染时未返回任何值。因此,用户具有初始值 []

在显示用户值之前,您可以使用可选的链接或检查加载状态。

return (
    <div className="card">
        <div className="card-header">
            {users[0]?.name}
        </div>
    </div>
)

或:

return loading ? null : (
    <div className="card">
        <div className="card-header">
            {users[0]?.name}
        </div>
    </div>
)

最好使用 || 运算符处理 name 属性为空字符串的情况:

return loading ? null : (
    <div className="card">
        <div className="card-header">
            {users[0]?.name || "Anonymous"}
        </div>
    </div>
)
,

apiRequest花费3秒钟的时间来返回您的Javascript代码试图尽快编译的值。

如果您没有考虑readUsersundefined的3秒钟,则会出现错误。

这是因为readUsers被初始化为特殊值undefined,该特殊值没有可从中访问的方法或值。

如果您打开控制台并尝试输入undefined[0]undefined.toString(),则会出现错误,因为undefined上不存在任何内容。

为避免该错误,您应该提供一个后备功能,以便在某个值为undefined时执行此操作,然后在它变为另一个具有可访问的方法和值的值时,允许它们执行。

import React,{ useEffect,useState } from "react";

const oneSecond = 1000;
const threeSeconds = 3 * oneSecond;

// -> Fake API request
function apiRequest() {
  // -> Create a new Promise
  return new Promise((resolve) =>
    // -> Resolve the Promise after waiting three seconds
    setTimeout(() => resolve([{ name: "Bill" }]),threeSeconds)
  );
}

export default function App() {
  const [readUsers,writeUsers] = useState();
  useEffect(() => {
    // -> Make request (which takes 3 seconds),then update state
    apiRequest().then((users) => writeUsers(users));
  });
  return (
    <div>
      {readUsers ? (
        readUsers.map((user) => <div>{user.name}</div>)
      ) : (
        <div>Loading...</div>
      )}
    </div>
  );
}