【问题标题】:Why state doesn't keep all the data in Array state in hook when it updated in foreach?为什么状态在foreach中更新时不会将所有数组状态的数据保留在钩子中?
【发布时间】:2021-09-11 07:20:36
【问题描述】:

我想通过 foreach 更新我的 Array 状态,但它只保留最后一个。我还使用空数组进行 useEffect 以通过更新状态来停止每次重新渲染。

import './App.css';
import Card from "./Card"
import Books from "./Books"
import { useEffect, useState } from 'react';
import axios from "axios"
import BooksInfo from './Books';
function App() {
  const [bookInfo,setBookInfo] = useState([])
  useEffect( ()=>{
    let bname = ""
    let bauthor = ""
    let bcover = 0
    async function getInfo(){
        let results = Promise.all(BooksInfo.map(book=>{
          let result = axios.get(`https://openlibrary.org/search.json?q=${book}`)
          return result
        }))
        ;(await results).forEach(result=>{
          console.log(result)
            bname= result.data.docs[0].title_suggest
            bauthor= result.data.docs[0].author_name[0]
            bcover= result.data.docs[0].cover_i
            setBookInfo([...bookInfo , { name:bname , author:bauthor  , cover:bcover }]);
            console.log(bookInfo)
        })
    }

    getInfo()
  },[])  

这是其中一个 cmets 的附加代码:此代码帮助我了解 state 和 useEffect 的工作原理。

function App(){
  console.log("App Rendered!");

  const [counter, setCounter] = useState(0);
  const [test, setTest] = useState(0)
  const [run,setRun] = useState(0)
  useEffect(()=>{
    console.log("inside useEffect")
    setCounter(counter => counter + 1);
    setTest(test => test +counter)

  },[run])
  const count= ()=>{
    console.log("test")
    setRun(run => run + 2)
  }
  return (
    <div>
      <h1>Counter: {counter}</h1>
      <button
        onClick={count}
      >
        Increment
      </button>
    </div>
  );
}
export default App;

【问题讨论】:

    标签: javascript reactjs foreach react-hooks state


    【解决方案1】:

    setBookInfo 函数是异步的,因此无法保证在每次迭代后,bookInfo 的数据会使用新插入的数据进行更新。 map函数更适合你的情况

    const newBookInfor = (await results).map((result) => {
        let bname = "";
        let bauthor = "";
        let bcover = 0;
        bname = result.data.docs[0].title_suggest;
        bauthor = result.data.docs[0].author_name[0];
        bcover = result.data.docs[0].cover_i;
        return { name: bname, author: bauthor, cover: bcover };
    });
    setBookInfo(newBookInfor);
    

    【讨论】:

    • 主要问题不是setBookInfo是异步的;问题是状态在组件的特定渲染中是恒定的。组件无法看到更新的状态直到它重新渲染。
    • 他在setBookInfo上使用了扩展运算符,它将创建一个bookInfo变量的新引用。
    • 扩展语法将创建一个新数组,但状态将相同,它不包括在 forEach() 方法的上一次迭代中添加的对象。
    • 这听起来很奇怪。你能告诉我the state will be the same的原因吗?
    • @dothuan 因此,当我们立即更新 useEffect 中的状态时,组件将重新渲染,以便它可以看到状态的新值,但状态直到结束才能使用它们的新值的使用效果,使另一个渲染。我更新了上面的代码,并添加了小代码以提供帮助,因此请尝试一下。它将帮助您更好地理解。
    【解决方案2】:

    试试这个,setBookInfo 是一个异步调用,当你在循环中使用它时,它不会为下一次迭代取最新值。相反,它采用最后一个值(初始值)。这就是它显示最后一个值的原因。

    import "./App.css";
    import Card from "./Card";
    import Books from "./Books";
    import { useEffect, useState } from "react";
    import axios from "axios";
    import BooksInfo from "./Books";
    function App() {
      const [bookInfo, setBookInfo] = useState([]);
      useEffect(() => {
        async function getInfo() {
          let results = await Promise.all(
            BooksInfo.map((book) => {
              let result = axios.get(
                `https://openlibrary.org/search.json?q=${book}`
              );
              return result;
            })
          );
    
          const finalResult = results.map((result) => {
            let bname = "";
            let bauthor = "";
            let bcover = 0;
            console.log(result);
            bname = result.data.docs[0].title_suggest;
            bauthor = result.data.docs[0].author_name[0];
            bcover = result.data.docs[0].cover_i;
            return { name: bname, author: bauthor, cover: bcover };
          });
          setBookInfo([...bookInfo, ...finalResult]);
        }
        getInfo();
      }, []);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 2021-08-17
      • 1970-01-01
      • 2022-01-07
      • 2018-11-24
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多