我有一个 React 上下文,它将在一个对象中为我保存大量文件名列表。每个文件名数组都将与给定的
camId
相关联。
因此,水合后,filenamesObj 应如下所示:
{
cam1: [file1, file2, file3]
cam2: [filea, fileb, filec]
// etc...
}
这是上下文和提供者的代码:
export const FilenamesContext = createContext()
export const FilenamesProvider = ({ children }) => {
const [filenamesObj, setFilenamesObj] = useState({})
const addFilenames = ({ camId, incomingFilenamesArr }) => {
let newFilenamesArr
if (filenamesObj[camId]) {
newFilenamesArr = combineAndSortArrays(filenamesObj[camId], incomingFilenamesArr)
} else {
newFilenamesArr = incomingFilenamesArr
}
console.log('newFilenamesArr :>> ', newFilenamesArr); // THIS PRINTS THE CORRECT VALUE
setFilenamesObj({ ...filenamesObj, [camId]: newFilenamesArr })
}
return (
<FilenamesContext.Provider
value={{
filenamesObj,
addFilenames,
}}
>
{children}
</FilenamesContext.Provider>
)
}
然后我将其放入反应组件中,它实际上只是显示文件名 - 这是一个概念验证:
export default function CameraDetails() {
let { camId } = useParams()
let { filenamesObj } = useFilenames()
return (
<>
<FilenamesLoader camId={camId} />
<Typography>Cam file names {camId}</Typography>
{JSON.stringify(filenamesObj)}
<Link to={"/"}>Go HOME</Link>
</>
)
}
注意,
filenamesLoader
组件应该进行 API 调用并通过 addFilenames 函数(上面定义)将结果加载到 FilenamesContext 中:
export default function CameraLoader({ camId }) {
const { filenamesObj, addFilenames } = useContext(FilenamesContext)
useEffect(() => {
async function getAllFilenames(camId, before, count = 1) {
if (count > 5) {
console.log("count reached 5") // keeps this from being an infinite loop
return
}
let returnedFilenames = await api.getFilenames({ camId, before })
addFilenames({ camId, incomingFilenamesArr: returnedFilenames })
await getAllFilenames(camId, getDateFromFilename(returnedFilenames[returnedFilenames.length - 1]), count + 1)
}
getAllFilenames(camId)
}, [])
return null
}
但是,问题:是存储在上下文中的
filenamesObj
似乎永远不会记住该值...它显示第一个调用的值...更新以显示第二个调用的值.. .然后是第三个...最后,它总是只显示第 5 个 API 调用的值...而不是 5 个单独调用的组合。
我的猜想是上下文中的
filenamesObj
没有被更新(或者我正在使用它的“陈旧”值),因此setFilenamesObj({ ...filenamesObj, [camId]: newFilenamesArr })
实际上只是“传播”一个空对象而不是一个对象有价值观。
帮忙?
问题在于,通过递归调用该函数,会以陈旧状态调用该函数。
我将 addFilenames 函数更改为使用“prevState”的函数调用。新的工作函数如下所示:
const addFilenames = ({ camId, incomingFilenamesArr }) => {
setFilenamesObj((prevFilenamesObj) => {
let newFilenamesArr
if (prevFilenamesObj[camId]) {
newFilenamesArr = combineAndSortArrays(prevFilenamesObj[camId], incomingFilenamesArr)
} else {
newFilenamesArr = incomingFilenamesArr
}
return { ...prevFilenamesObj, [camId]: newFilenamesArr }
})
}
感谢@G Gallegos在这里回答:为什么需要带有功能更新表单的React useState?让我到达正确的地方