React Navigation跳转详情页Axios请求总显示上一条数据如何解决
问题根因
useEffect传入空依赖数组[],副作用逻辑仅会在组件首次挂载时执行一次。React Navigation默认采用栈式导航机制,页面跳转时不会销毁栈内已存在的页面实例,从首页跳转至不同电影的详情页时,DetailsScreen组件不会触发重新挂载,仅会更新route.params传参,此时空依赖绑定的请求逻辑完全不会重新执行。- 请求地址
URL定义在useEffect作用域外部,副作用执行时会通过闭包捕获首次渲染时生成的URL值,后续路由参数更新后,闭包内留存的仍是旧的请求地址,直接导致接口返回上一次访问的电影数据。 - 新请求发起前没有重置组件状态,请求加载过程中页面会持续展示上一次留存的旧数据,最终表现为数据展示始终滞后一次。
修复方案
- 将
route.params.categoryWithId加入useEffect的依赖列表,确保路由参数变化时自动重新触发数据请求 - 把请求URL的生成逻辑移到
useEffect内部,避免闭包捕获旧的变量值 - 每次请求发起前先清空旧的
apis状态,避免加载过程中残留上一次的旧数据 - (可选)针对需要每次进入页面都强制刷新的场景(例如跨页面修改收藏状态后返回详情页同步数据),可以使用React Navigation提供的
useFocusEffect钩子替代普通useEffect
修复后基础实现代码
const DetailsScreen = ({ route, navigation }) => { const [apis, setApis] = useState([]); useEffect(() => { // 请求发起前清空旧数据,避免旧内容残留 setApis([]); // URL生成逻辑移入副作用内部,规避闭包问题 const URL = "https://demoapi.com" + route.params.categoryWithId; console.log("Top ==>" + URL); async function getAllData() { try { const res = await axios.get(URL); setApis(res.data); } catch (error) { console.log(error); } } getAllData(); // 路由参数加入依赖数组,参数变化时重新执行请求 }, [route.params.categoryWithId]); if (!apis.length) return null; console.log("details ==> " + JSON.stringify(apis)); return ( <> <ImageBackground source={{ uri: apis[0].image }} resizeMode="cover" style={styles.backgroundImage} > <Wrapper> <ImageBackground resizeMode="contain" source={{ uri: "https://pngimg.com/uploads/netflix/netflix_PNG32.png", }} style={styles.platformLogo} /> <Title>{apis[0].title}</Title> <SubTitle>{apis[0].date}</SubTitle> <PlayIcon style={{ backgroundColor: "white", borderRadius: 50, }} /> </Wrapper> </ImageBackground> <StatusBar hidden /> </> ); };
可选:页面聚焦自动刷新实现
如果需要每次页面获得焦点都刷新数据,可替换为useFocusEffect写法,注意要配合React.useCallback包裹避免重复执行:
import { useFocusEffect } from '@react-navigation/native'; const DetailsScreen = ({ route, navigation }) => { const [apis, setApis] = useState([]); useFocusEffect( React.useCallback(() => { setApis([]); const URL = "https://demoapi.com" + route.params.categoryWithId; async function getAllData() { try { const res = await axios.get(URL); setApis(res.data); } catch (error) { console.log(error); } } getAllData(); }, [route.params.categoryWithId]) ); if (!apis.length) return null; // 其余JSX渲染逻辑和基础实现保持一致 };
内容的提问来源于stack exchange,提问作者cre8tivestudy
相关产品推荐
相关产品推荐

