React Context的listProduct初始加载后读取为undefined问题求助
问题原因
核心是函数作用域内的同名变量声明导致的暂时性死区问题,和Context本身无关:
- 你在
pickImage函数内部,用const重新声明了一个和外层Context取出的变量同名的listProduct变量 - JS预解析时会将整个
pickImage作用域内的listProduct标识符绑定到这个内部声明的变量上,而const声明的变量存在暂时性死区:在声明语句执行前访问该变量,就会出现取值异常(部分非严格模式环境不会抛出引用错误,直接返回undefined) - 初始渲染时外层
console.log输出正常,是因为访问的是外层作用域的Context变量,没有被内部声明影响。
解决方案
任选一种修改方式即可:
方式1:修改内部变量名,避免命名冲突
把pickImage函数内部声明的listProduct改成其他不冲突的名称,比如newListProduct:
const pickImage = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [4, 3], quality: 1, exif: true, }); // 此时访问的就是外层Context的listProduct,取值正常 console.log('before copy it is ', listProduct); const newListProduct = { ...product }; console.log('the list is', newListProduct); newListProduct.images.push(result.uri); setListProduct({ ...newListProduct }); return; };
方式2:使用setState的函数式更新写法(更推荐)
直接通过setListProduct的回调参数获取最新的Context状态,不需要依赖外部变量,也能避免状态更新不及时的问题,还建议增加用户取消选图的判断逻辑避免报错:
const pickImage = async () => { let result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [4, 3], quality: 1, exif: true, }); // 过滤用户取消选择的场景 if (result.canceled) return setListProduct(prevList => { return { ...prevList, images: [...prevList.images, result.uri] } }) return; };
内容的提问来源于stack exchange,提问作者Steven
相关产品推荐
相关产品推荐

