Svelte组件报错:无法读取null的current属性及unsubscribe不是函数
问题分析与修复方案
错误原因
- "TypeError: unsubscribe is not a function":在
subscribe回调中直接调用unsubscribe()时,unsubscribe变量还未完成赋值——subscribe会立即执行回调,此时变量还没拿到返回的取消订阅函数。 - "Cannot read properties of null (reading 'current')":你的
loading判断仅检查value !== undefined,但如果store返回的value是null或不含current属性的对象,loading会被设为false,渲染时访问$currentOneCallData.current就会触发读取null属性的错误。
修复方案(推荐:自动订阅)
移除手动订阅逻辑,改用Svelte原生的$语法自动监听store变化,Svelte会自动处理订阅与取消订阅,完全避免手动管理的错误。同时优化loading的判断逻辑,确保数据真正可用后再渲染。
修复后完整代码
<script> import rain from "../assets/icons/d-rain.png"; import { currentOneCallData } from "../cli"; // 响应式判断:仅当store数据存在且包含current属性时,才结束loading $: loading = !($currentOneCallData?.current !== undefined); function convertUnixTimestamp(timestamp) { const months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ]; const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; const date = new Date(timestamp * 1000); const day = days[date.getDay()]; const month = months[date.getMonth()]; const dayOfMonth = date.getDate(); return `${day}, ${month} ${dayOfMonth}`; } </script> {#if !loading} <div class="current-container"> <div class="text-content"> <div class="dateAndTime"> <p class="date">{convertUnixTimestamp($currentOneCallData.current.dt)}</p> <p class="time">7:40 AM</p> </div> <p class="temp">{$currentOneCallData.current.temp}<sup class="temp-unit">°C</sup></p> <h4 class="feel-container"> Feels like <span class="feel">{$currentOneCallData.current.feels_like} <span class="temp-unit">°C</span></span> </h4> <h3 class="desc">{$currentOneCallData.current.weather[0].description}</h3> </div> <div class="icon-container"> <img src={rain} alt="Rain icon" class="icon" /> </div> </div> {:else} <div class="loading"><p>Loading...</p></div> {/if}
关键修复点
- 用
$: loading = !($currentOneCallData?.current !== undefined)实现响应式判断:当store数据变化时,自动检查是否存在有效的current属性,确保数据可用后才结束loading。 - 移除了
onMount、onDestroy中的手动订阅逻辑,无需再处理unsubscribe,Svelte会在组件销毁时自动取消订阅,彻底解决unsubscribe is not a function错误。 - 给img标签补充了有意义的alt文本,提升页面可访问性。
备选方案(保留手动订阅)
如果必须保留手动订阅模式,需要修复unsubscribe未赋值的问题,并优化数据判断逻辑:
<script> import { onDestroy, onMount } from "svelte"; import rain from "../assets/icons/d-rain.png"; import { currentOneCallData } from "../cli"; let unsubscribe; let loading = true; onMount(() => { let isUnsubscribed = false; // 先保存订阅返回的取消函数 const unsubscribeFunc = currentOneCallData.subscribe(value => { if (!isUnsubscribed && value?.current !== undefined) { loading = false; unsubscribeFunc(); isUnsubscribed = true; } }); unsubscribe = unsubscribeFunc; }) onDestroy(() => { if (unsubscribe) { unsubscribe(); } }); // convertUnixTimestamp函数保持不变 </script> <!-- 模板部分保持不变 -->
内容的提问来源于stack exchange,提问作者Nico
相关产品推荐
相关产品推荐

