【发布时间】:2020-04-07 00:12:23
【问题描述】:
假设我有一段逻辑(例如搜索栏),我想在这段时间内显示一个微调器。所以我有以下代码:
this.state = {
searching: false,
}
invokeSearch() {
this.setState({ searching: true })
const fuse = new Fuse(arrayOfData, { keys: [name: 'title'] })
const searchResults = fuse.search(searchTerm)
this.setState({ searching: false })
}
我将 searching 布尔值存储在状态中,以便我可以将它传递给组件以显示或隐藏微调器。
我知道这不起作用,因为setState 是异步的,因此根据文档,我可以改用回调。
setState() 的第二个参数是一个可选的回调函数,一旦 setState 完成并重新渲染组件,就会执行该回调函数。通常我们建议使用 componentDidUpdate() 来代替此类逻辑。
所以我的代码现在看起来像这样:
this.state = {
searching: false,
}
invokeSearch() {
this.setState({ searching: true }, () => {
const fuse = new Fuse(arrayOfData, { keys: [name: 'title'] })
const searchResults = fuse.search(searchTerm)
this.setState({ searching: false })
})
}
但是,这并没有按预期工作。将 this.state.searching 渲染为 <Text> 组件或在某些三元逻辑中显示/隐藏微调器不会明显地从 false 更改。
我猜这与 setState 的异步批处理性质有关,这导致它不起作用?
为了解决这个问题,我一直在使用以下解决方案,对我来说这似乎是一个 hack:
this.state = {
searching: false,
}
invokeSearch() {
this.setState({ searching: true }
setTimeout(() => {
const fuse = new Fuse(arrayOfData, { keys: [name: 'title'] })
const searchResults = fuse.search(searchTerm)
this.setState({ searching: false })
}, 0)
}
谁能向我解释为什么回调不能按我预期的那样工作,以及如何以更优雅的方式解决这个问题?
编辑:修正问题
感谢您提供的所有有见地的答案和 cmets。进一步调查后,我觉得 Fuse 不是这个问题的好例子。我还有另一个异步 Redux 示例,我将在下面描述
当我点击一个按钮时,我的目标是显示一个微调器,更新 Redux 存储(它反过来重新呈现项目列表),然后隐藏微调器。 Redux 使用的是 Thunk,所以它是异步的,我在操作上有一个回调设置。 reducer 没有做任何花哨的事情,只是用新的数据值更新 Redux 存储。
// action
export function updateFilters(filters, successCallback = () => {}) {
return (dispatch) => {
dispatch({ type: ACTIONS.UPDATE_FILTERS, data: filters })
successCallback()
}
}
// component
changeFilter = (filters) => {
this.setState(() => ({
loading: true,
}), () => {
updateFilters(filters, () => {
this.setState({
loading: false,
})
})
}
}
微调器仍然没有渲染!
【问题讨论】:
-
您发布的所有方法都不起作用,因为您正在调用异步函数。还向我们提供异步功能代码。
-
可以/不应该在异步方法的回调中设置
searching: false(只要它实际完成)? -
根据代码的样子,你的搜索函数应该返回一个
Promise,然后你应该在 Promise 解决/拒绝后更新状态:fuse.search(searchTerm).then(() => this.setState({ searching: false })) -
@kinduser 正如我所说,最后一种方法确实有效。
-
@scgough 抱歉,我正在使用我认为实际上是同步的 Fuse.js。我已经更新了我的问题。
标签: javascript reactjs react-native react-state-management react-state