javascript - 在渲染之前重置 React 状态
问题描述
我正在构建一个使用 TMDB Api 的 Web 应用程序。我有以下代码可以获取有关电视节目的所有信息
export const useShowInfoFetch = ({showId}) => {
const [data, setData] = useState({})
const [loading, setLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchShowInfo = useCallback(() => {
setLoading(true)
try {
axios.get(getShowInfo(showId))
.then(response => {
setData(response.data)
})
} catch (error) {
_setError(true)
} finally {
setLoading(false)
}
}, [showId])
useEffect(() => {
fetchShowInfo()
}, [fetchShowInfo])
return [data, loading, _error]
}
获取的所有信息都显示在页面中,该页面还具有带有react-router-dom 的链接。这些链接转到另一个电视节目页面。问题是,当我在一个包含 X 季数量的电视节目的页面中单击一个具有较少季节的电视节目时,我所在页面的季节会持续一段时间。因此,当我获取每个季节的信息时,我在页面中得到了一个 404,它的季节较少。
这是错误的屏幕截图
橙色圆圈是它显示的内容,因为我单击了季节较少的电视节目。如您所见,上一页中的季节持续了一段时间,并且由于 The Alienist 只有 2 个季节(不是 9 个),我得到了 404。您还可以注意到后者,显示了正确的季节数量。
我试图在useEffect挂钩中添加一个清理方法。像这样的东西:
useEffect(() => {
fetchShowInfo()
return function cleanup() {
setData({})
}
}, [fetchShowInfo])
但这没有用。
我知道在当时的 Axios 承诺之后我可以通过捕获来处理这个问题,但我想弄清楚为什么会发生这种情况,并用一个好的解决方案来解决这个问题,而不是避免它。
欢迎任何帮助,如果需要,我可以与所有代码共享存储库。
编辑:
为了显示类似的电影,我使用了另一个自定义钩子
export const useSimilarFetch = (elementType, elementId) => {
const [similarElements, setSimilarElements] = useState({elements: []})
const [similarLoading, setSimilarLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchSimilarElements = useCallback(async (endpoint) => {
console.log(">>> fetching similar elements <<<")
setSimilarLoading(true)
try {
await axios.get(endpoint)
.then(response => {
setSimilarElements(() => ({
elements: [...response.data.results],
currentPage: response.data.page,
totalPages: response.data.total_pages
}))
})
} catch (error) {
_setError(true)
} finally {
setSimilarLoading(false)
}
}, [])
useEffect(() => {
fetchSimilarElements(getSimilar(elementType, elementId));
}, [fetchSimilarElements, elementType, elementId])
return [{similarElements, similarLoading, _error}, fetchSimilarElements]
}
然后,在我的 ShowInfoComponent 中,我调用所有需要的钩子,如下所示:
const {showId} = useParams()
const [data, loading, _error] = useShowInfoFetch({showId})
const [{similarElements, similarLoading}] = useSimilarFetch("tv", showId)
谢谢。
解决方案
到时间showId
变化时,data
必须等待一个额外的渲染周期,因此showId
即使data
尚未获取,也已使用。UI 既依赖于showId
and data
,又data
依赖于showId
. data
解决此问题的一种方法可能是让您的 UI单独依赖。身份证呢?例如添加它data
。我们只是想避免去同步。
像这样的东西:
export const useShowInfoFetch = ({showId}) => {
const [data, setData] = useState({})
const [loading, setLoading] = useState(false)
const [_error, _setError] = useState(false)
const fetchShowInfo = useCallback(() => {
setLoading(true)
try {
axios.get(getShowInfo(showId))
.then(response => {
setData({ id: showId, info: response.data})
})
} catch (error) {
_setError(true)
} finally {
setLoading(false)
}
}, [showId])
useEffect(() => {
fetchShowInfo()
}, [fetchShowInfo])
return [data, loading, _error]
}
然后用于data.id
建立您的链接。如果 response.data
已经包含 id,那么更好的是,使用它。
当然,这只是一个例子,但希望你能明白这一点。
推荐阅读
- python - 在虚拟环境中安装 pyodbc 时出错
- python-3.x - 如何将excel内容转换为python字典
- java - 需要在java中的方法内的字符串中添加默认值
- sql-server - 如何在 SQL Server 中查找两个不同日期之间的天数?
- python - 无法使用请求库 python 检索 api 令牌
- c# - EPPlus:复制现有 Excel 工作表时无法访问已关闭的 Stream
- c++ - 这个 C 函数有什么类型的函数参数声明?
- c# - 右键单击单元格文本启用 C# Excel 插件功能区
- bash - 如果文件在 N 秒内没有更改,取消“tail -f”?
- java - Android Studio:消息“在项目结构对话框中配置项目”