Vue使用Fetch API遇空值读取错误,求替代React useEffect方案
问题:Vue异步获取产品数据后模板不更新,且出现访问null属性错误
我想要从API获取产品数据,问题在于模板不会等待异步函数执行完毕、products属性填充完获取的数据。由于这是异步函数,模板运行时products的值为null,访问products.value会抛出"cannot read properties of null (reading 'value')"错误。我尝试用v-if判断products是否存在后再渲染,但获取数据后products的变更未被捕获,页面无内容显示。在React中我可以通过useEffect API传入依赖数组指定products状态来触发更新,请问Vue中的等价实现方式是什么?
后端路由代码(Laravel)
Route::get('/products',function(){ $products = DB::table('products')->get()->toArray(); return response()->json([ 'products' => $products, ]); });
当前Vue组件代码
import { ref, watchEffect } from "vue"; const products = ref(null); watchEffect(() => { fetch("/products") .then((response) => response.json()) .then((data) => (products.value = data)); }); <template> <div v-if="products"> <ul v-for="product in products.value"> <li class="py-4 px-2"> <Link href="..."> <img :src="product.imageUrl"/> <p>{{ product.name }}</p> </Link> </li> </ul> </div> </template>
解决方案
1. 用onMounted替代watchEffect(对应React的useEffect(() => {}, []))
Vue中与React空依赖useEffect等价的是onMounted钩子,它只会在组件挂载时执行一次,完全匹配初始化获取数据的场景,无需额外追踪依赖:
import { ref, onMounted } from "vue"; const products = ref(null); onMounted(() => { fetch("/products") .then((response) => response.json()) .then((data) => { // 后端返回的是包含products数组的对象,需赋值数组本身 products.value = data.products; }); });
2. 修正模板中的数据访问逻辑
Vue的ref在模板中会自动解包,不需要手动写.value,直接使用变量名即可:
<template> <!-- 直接判断products是否存在,ref自动解包 --> <div v-if="products"> <!-- 循环products数组,无需添加.value --> <ul v-for="product in products" :key="product.id"> <li class="py-4 px-2"> <Link href="..."> <img :src="product.imageUrl"/> <p>{{ product.name }}</p> </Link> </li> </ul> </div> <!-- 可选:添加加载状态提示 --> <div v-else>加载中...</div> </template>
关键问题说明
- 之前用
watchEffect虽然能运行,但它会追踪依赖并重复执行,而初始化获取数据只需要执行一次,onMounted更语义化且性能更优。 - 后端返回的
data是{products: [...]}结构,之前直接把products.value设为整个data,导致模板中访问的是对象而非数组,这是数据赋值的核心错误。 - Vue的
ref在模板中自动解包,这是和React状态使用的关键区别,不需要像在脚本中那样手动调用.value。
内容的提问来源于stack exchange,提问作者ahmad kharabsheh
相关产品推荐
相关产品推荐

