【发布时间】:2022-12-10 22:43:39
【问题描述】:
我在名为 handleLinkChange 的输入字段上有一个 onClick 事件,该事件验证其内容(YouTube 链接),如果它有效,则调用提取其 YouTube id 的函数。
在 onClick 事件中,我更新了链接状态,以便用户查看链接是否有效以及是否正在进行 ID 提取(由输入字段中的加载轮指示)。此时,状态会根据需要在 DOM 中更新。但是,当我在设置状态后到达getIdsFromLink函数时,链接状态仍然是初始值。这使得无法更改链接,例如,在解析 id 后用复选标记替换链接的加载指示器。
// Links state
const [links, setLinks] = useState([{ link: '', state: IS_VALID, errorMessage: '' }])
// onChange event handler
const handleLinkChange = (event, index) => {
const clonedLinks = [...links]
let value = decodeURI(event.target.value.trim())
const { passesRegex, validityMessage } = checkLinkValidity(value)
clonedLinks[index] = {
link: value,
state: passesRegex ? IS_VALIDATING_SERVER_SIDE : IS_ERROR,
errorMessage: validityMessage,
}
setLinks(clonedLinks)
if (clonedLinks[index] !== '' && passesRegex) {
getIdsFromLink(clonedLinks[index].link, index)
}
}
// Parser
const getIdsFromLink = (link, index) => {
console.log('links state', links) // initial state
socket.emit('getIds', link)
socket.on('idsParsed', newIds => {
console.log('links state after parse', links) // initial state
})
}
// Shortened return
return (
links.map((link, index) => (
<Input
value={link.link}
onChange={event => handleLinkChange(event, index)}
/>
{link.link && (
<FontAwesomeIcon
icon={link.state === IS_VALID ? faCheck : link.state === IS_ERROR ? faTimes : faSpinner}
/>
)}
)
))
我知道状态是异步的,我也尝试用 useEffect 观察状态变化,但我无法以这种方式重构我的代码,而且我有另一个严重依赖于链接状态的状态对象,所以我放弃了那个.
即使当我尝试使用 flushSync 同步更新状态时,我也有同样的效果。
非常感谢您的帮助!谢谢!
【问题讨论】:
-
clonedLinks代表您当前的状态,因此您可以将其传递给getIdsFromLink()。如果您计划使用getIdsFromLink中的第二个setLinks()调用来更新您的状态,那么您应该删除第一个setLinks()调用,因为它会被您所做的第二个setLinks()调用覆盖。您还可以使用setLinks(currLinks => ...)访问当前状态值 -
@NickParsons 我不将
clonedLinks传递给getIdsFromLink()的原因是在解析id(这是一个套接字调用)期间,用户可以添加更多链接,因此,当链接解析完成时,它的clonedLinks可能无法反映链接状态的最新变化。此外,在解析之前我需要setLinks(),以便用户看到输入旁边的加载指示器。 -
@NickParsons 实际上使用带有函数参数的
setLinks可以访问当前状态,所以我在上面评论中描述的问题已经解决了!所以现在我在函数参数中更改我的links对象并在最后返回新对象。我只需要确保克隆函数参数的当前状态对象以强制重新呈现状态。
标签: javascript reactjs react-hooks