我处于这种状态:
const [fingerprintingIssues, setFingerprintingIssues] = React.useState([])
我有一个遍历一堆数据进行验证的功能。如果有错误,它将与fingerprintingIssues
一起添加到setFingerprintingIssues
中。很好。
但是在此方法(缩写)中,我正在方法fingerprintingIssues
内检查complete
,并且它始终返回[]
。我已经读到这是闭包和陈旧状态的问题,但我似乎看不出这在这里如何适用。
const validateDocument = data => {
const start = moment()
try {
Papa.LocalChunkSize = 10485
return Papa.parse(data, {
complete: () => {
// Log completion only if it’s been 20 seconds or more
const end = moment()
const duration = moment.duration(end.diff(start))
const seconds = Math.ceil(duration.asSeconds())
if (seconds < MIN_PROCESS_TIME) {
setTimeout(() => {
setUploadStep('tagging')
console.log('fingerprintingIssues', fingerprintingIssues)
}, (MIN_PROCESS_TIME - seconds) * 1000)
} else {
setUploadStep('tagging')
}
},
error: () => {
setDocumentError(true)
setDocumentReady(false)
},
})
…
有什么建议吗?
答案 0 :(得分:0)
我认为确实存在关闭和陈旧状态的问题。使用挂钩时,您需要谨慎使用回调。
您的组件函数被调用多次(每个渲染一次)。每个呼叫将收到一个特定的状态。您可以将其想像成特定状态与该特定渲染相关联。如果在渲染中创建回调,则该回调将存在于其创建所在的渲染的闭包中。问题是,如果重新渲染组件,则该回调仍存在于旧渲染的闭包中,并且将没有看到新状态。
解决此问题的一种方法是使用React.useRef,您可以阅读有关here的更多信息。引用具有一个值,可以随时进行修改和访问,而无需关闭。请注意,修改参考不会导致您的组件重新呈现。
const fingerPrintingIssues = React.useRef([])
const validateDocument = data => {
// Perform validation
// Now access (refs are accessed by .current)
console.log(fingerPrintingIssues.current)
}
// Modify:
fingerPrintingIssues.current.push(...)
如果在修改值时需要重新渲染组件,则可以结合使用useRef()和useState()。