【问题标题】:Do I have to set every properties initial value in useState?我是否必须在 useState 中设置每个属性的初始值?
【发布时间】:2020-12-27 12:13:05
【问题描述】:

我是 React 的初学者。我有一个向 API 发出请求并将响应作为 JSON 返回的函数

 const [datastate, setData] = useState({});
 const getData = async () => {
     const response = await fetch(`https://MY_API_REQUEST_URL_HERE`);
     const data = await response.json();
     setData(data);
     console.log(data);      // works
     console.log(datastate); // Empty object is returned in console 
 }

我想使用从 API 返回的响应来初始化我的 datastate,即使用 data 变量。

但我最近发现它返回空对象的原因是因为我没有在 useState 中定义任何属性,所以准确地说我必须这样做:

const [datastate, setData] = useState({
    username: "",
    firstname: "",
    lastname: "",
});

但问题是API返回的数据很复杂,它包含一个对象数组,一个对象包含另一个对象包含数组。所以我在想有没有捷径可以做到这一点,那就是我不必在 useState 中定义我想使用的每个属性。

App.js:

import React, {useEffect, useState} from "react";
import Data from "./Data";
import './App.css';

function App() {
    const [datastate, setData] = useState({});
    useEffect(() => {
        getData();
    }, [datastate]);  // Added as suggested by William Wang

    const getData = async () => {
        const response = await fetch(`https://api.edamam.com/api/nutrition-data?app_id=${process.env.REACT_APP_APP_ID}&app_key=${process.env.REACT_APP_APP_KEY}&ingr=1%20pie%20pizza`);
        const data = await response.json();
        setData(data);
        console.log(data);
        console.log(datastate);
    }
    return (
        <div className="App">
            <form className="search-form">
                <input className="search-bar" type="text" />&nbsp;
                <button className="search-button" type="submit">Search</button>
            </form>
            <Data data={datastate} />
        </div>
    );
}
export default App;

请注意返回里面的JSX是不完整的,请关注返回里面的Data组件

数据.js

import React from "react";

function Data({data}) {
    return(
        <div>
            <p>
                {data.users[0].username}
            </p>
        </div>
    );
}
export default Data;

另请注意,data.users 会出现错误,就好像没有将任何道具传递给 Data 组件一样。

【问题讨论】:

  • 状态是异步更新的。即使您为状态提供初始值,在调用 setData 后立即记录 datastate 也会为您提供以前的状态,而不是新的状态。如果要记录更新后的状态值,请使用useEffect hook:useEffect(() =&gt; { console.log(datastate); }, [datastate]);
  • 您必须在 vue 中设置默认值,其中设置状态的工作方式不同(有利有弊),但我认为这在反应中没有必要。其他 cmets 和答案提到的适用,但我不明白,为什么设置初始属性会导致行为改变。你仍然会得到你设置的初始值。

标签: javascript reactjs react-hooks


【解决方案1】:

setData是异步方法,所以不能在setData()之后立即获取datastate的更新值

const getData = async () => {
     const response = await fetch(`https://MY_API_REQUEST_URL_HERE`);
     const data = await response.json();
     setData(data);
     console.log(datastate); // old value of `datastate` will be displayed.
 }

您应该使用useEffect() 来获取更新后的值。

useEffect(() => {
  console.log(datastate);
}, [datastate]);

更新

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

    useEffect(() => {
        console.log(datastate);
    }, [datastate]);  // Added as suggested by William Wang

    const getData = async () => {
        const response = await fetch(`https://api.edamam.com/api/nutrition-data?app_id=${process.env.REACT_APP_APP_ID}&app_key=${process.env.REACT_APP_APP_KEY}&ingr=1%20pie%20pizza`);
        const data = await response.json();
        setData(data);
        console.log(data);
        console.log(datastate); // This is wrong way to check the updated datastate value.
    }

【讨论】:

  • 我无法访问组件中的数据,为什么?在控制台中,console.log(datastate) 首先打印空对象,然后console.log(data)console.log(datastate) 正确打印对象多次,但我无法访问组件中的对象,就好像没有传递数据一样
  • 你需要调用 getData() 而不是在具有数据状态依赖的 useEffect 中,而只是在另一个具有空依赖关系的 useEffect 中调用它,这意味着 componentDidMount。我的意思是你不能在 setData() 之后立即 console.log() 更新的数据状态,但你只需要在 useEffect() 中检查它并添加一个数据状态依赖项,该依赖项总是在更新数据状态时触发。跨度>
  • 所以我将有 2 个 useEffect 一个具有数据状态依赖项,另一个没有任何内容,我必须调用 getData() 所以代码看起来像这样对吗? useEffect ( () =&gt; {}, [datastate] )useEffect ( () =&gt; { getData() } ) useEffect 内部的函数与 datastate 依赖有一个空的主体,可以吗?
  • 您可以在检查datastate是否正确更新后删除datastate依赖useEffect。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 2023-02-06
  • 2013-08-28
  • 1970-01-01
  • 2016-02-24
  • 2021-05-20
相关资源
最近更新 更多