next.js React,useState验证函数获取旧的状态值

e5nszbig  于 2023-06-22  发布在  React
关注(0)|答案(1)|浏览(131)

我有这个应用程序,扫描一个NFC标签,并创建一个列表。

import {useState} from "react";

const App = () => {
   const [tags, setTags] = useState([]);
   async function scanTag() {
      const ndef = new NDEFReader()
      await ndef.scan()
      ndef.onreading = ({serialNumber} => {
         if(validate(serialNumber)) return alert("already registered")
         let tag = {
            id: serialNumber
            //some other data...
         }
         const list = tags
         list.push(tag)
         setTags(list)
      })
   }
   function validate(id) {
      if(tags.find(tag => tag.id == id)) return true
      return false
   }
   function deleteTag(index) {
      setTags(
         tags.filter((_, i) => i !== index)
      )
   }
   return (
      <div>
         {
            tags.map((tag, index) => {
               return(
                  <div key={tag.id}>
                     <span>{tag.id}</span>
                     <button onClick={()=>{deleteTag(index)}}>Delete</button>
                  </div>
               )
            })
         }
         <button onClick={scanTag}>Scan Tag</button>
      </div>
   )
}

应用程序工作正常,直到我删除标签,重新扫描相同。验证函数触发并返回“已经扫描”。
控制台记录validate函数中的标签数组,显示了旧数组,所有标签仍在数组中。而deleteTag函数正确删除标记,我不知道为什么会发生这种情况。PS:由于我使用Chrome Android进行调试,我不能使用ReactDevTools。

wecizke3

wecizke31#

我认为你的问题可能是由于onreading回调函数。这是一个闭包函数,它将指向函数创建时的tags值。
最简单的方法是让闭包使用一个对象,因为即使值改变,对象的引用也总是相同的。我们可以使用useRef钩子。也可以使用setTags回调函数。

const tagsRef = useRef(tags);

// Ensure the tagsRef has the most recent tags state value
useEffect(() => {
   tagsRef.current = tags;
}, [tags]) 

async function scanTag() {
    const ndef = new NDEFReader()
    await ndef.scan()
    ndef.onreading = ({serialNumber} => {
        if(tagsRef.current.find(tag => tag.id == serialNumber)) return alert("already registered")
        let tag = {
            id: serialNumber
            //some other data...
        }

        // Use the setters callback with spread.
        setTags(prev => [...prev, tag]);
    })
}

相关问题