【问题标题】:Cannot read property ... of undefined (property/value from context)无法读取未定义的属性...(来自上下文的属性/值)
【发布时间】:2020-10-20 07:48:28
【问题描述】:

我收到来自 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 则没有值(未定义)?

【问题讨论】:

  • 在 axios 请求完成之前,users[],因此 users[0] 是未定义的。
  • @ChrisG aaaaaaaaaah 为什么我忘了...谢谢:D

标签: javascript reactjs react-context


【解决方案1】:

这是因为request还没有返回结果,用户还在[], 因此,要解决问题,您应该执行以下操作:

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

【讨论】:

    【解决方案2】:

    这是因为 useEffect 钩子内的请求是异步的,并且在第一次渲染时没有返回任何值。所以 users 具有初始值 []

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

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

    【讨论】:

      【解决方案3】:

      在此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>
        );
      }
      
      

      【讨论】:

        猜你喜欢
        • 2020-12-08
        • 1970-01-01
        • 2020-08-01
        • 1970-01-01
        • 2019-06-12
        • 2011-08-25
        • 1970-01-01
        • 2023-03-11
        • 2019-03-14
        相关资源
        最近更新 更多