React Hook值未即时更新 调用异步pickImage后props.route参数报错问题
问题根因与修复方案
根因说明
- useState的更新动作是异步批量执行的,调用
setImage后,当前渲染闭包内的image变量还是本次渲染初始的旧值,要等到组件触发重渲染后,image才会更新为新值,所以调用setImage后立即打印必然拿到旧值。 props.navigation.navigate的传参写法错误:React Navigation的navigate方法仅接收2个参数,第一个为目标路由名,第二个为要传递的参数对象,你传入的第三个参数album会被直接忽略,异常的传参逻辑可能导致路由参数被意外污染,触发props.route.params.uid读取报错。- 删除跳转代码后第二次打印拿到上次URI的现象,正好对应异步更新的逻辑:第二次调用
pickImage时,组件已经完成了第一次选图后的重渲染,此时闭包内的image是第一次更新后的值,所以打印出来的是上次选择的URI。
修复方案
- 跳转传参时直接使用你拿到的
result.uri,不要用还没更新的state变量 - 修正
navigate的传参格式,把要传递的参数封装为对象 - 给
props.route.params的读取加可选链防护,避免空值报错 - 如果需要监听路由参数变化,把
props.route.params.uid加入useEffect的依赖数组
修复后代码
const [album, setAlbum] = useState(""); const [hasGalleryPermission, setHasGalleryPermission] = useState(null); const [image, setImage] = useState(null); useEffect(() => { // 加可选链避免空值报错 const uid = props.route?.params?.uid; if (uid) setAlbum(uid); (async () => { const galleryStatus = await ImagePicker.requestMediaLibraryPermissionsAsync(); setHasGalleryPermission(galleryStatus.status === "granted"); })(); // 把uid加入依赖数组,参数变化时自动更新 }, [props.route?.params?.uid]); const pickImage = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [1, 1], quality: 1, }); console.log(result); if (!result.cancelled) { const newImageUri = result.uri; setImage(newImageUri); console.log(newImageUri); console.log(album); // 修正传参格式,直接用拿到的新uri,不用等待state更新 props.navigation.navigate("Save", { image: newImageUri, album: album }); } };
内容的提问来源于stack exchange,提问作者Simon Pintz
相关产品推荐
相关产品推荐

