You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React函数组件传递SoundAlarmService给子组件时为null的问题

React函数组件传递服务实例给子组件的问题解决

问题根源

你用普通变量alarmService存储服务实例,但React函数组件每次渲染都会重新声明并初始化该变量。当setInitialized(true)触发组件重新渲染时,alarmService会被重置为null,导致子组件拿到的始终是null。另外你的useEffect未设置依赖数组,会重复执行初始化逻辑,属于不必要的性能损耗。

解决方案

方案1:使用useState存储服务实例(推荐,状态变化自动触发渲染)

将服务实例存入React状态,初始化完成后更新状态,确保渲染时能获取到有效实例:

import { useState, useEffect } from 'react';
import SoundAlarmService from './SoundAlarmService'; // 注意修正类名拼写

export const MainTimer = () => {
  // 用state存储服务实例,初始值为null
  const [alarmService, setAlarmService] = useState<SoundAlarmService | null>(null);

  useEffect(() => {
    const initAlarmService = async () => {
      const service = await SoundAlarmService.CreateAsync();
      setAlarmService(service);
    };
    initAlarmService();
  }, []); // 空依赖数组确保初始化只执行一次

  // 直接通过alarmService是否存在判断初始化状态
  return !alarmService 
    ? <>Loading...</> 
    : (
      <View style={styles.container}>
        {timeConfired ? 
          <MainTimerAlarm 
            soundService={alarmService} 
            setTime={setTime} 
            time={time} 
            timeInfo={timer} 
            stopped={!timeConfired} 
          /> 
          : <></>}
        <SetMainTimer setTimer={setTimerFunc} setCancel={setCancel} />
      </View>
    ); 
}

方案2:使用useRef存储服务实例(适合无需触发渲染的场景)

如果服务实例的更新不需要触发组件重新渲染,可以用useRef存储,它的current属性不会随渲染重置:

import { useState, useEffect, useRef } from 'react';
import SoundAlarmService from './SoundAlarmService';

export const MainTimer = () => {
  const alarmServiceRef = useRef<SoundAlarmService | null>(null);
  const [initialized, setInitialized] = useState(false);

  useEffect(() => {
    const initAlarmService = async () => {
      const service = await SoundAlarmService.CreateAsync();
      alarmServiceRef.current = service;
      setInitialized(true);
    };
    initAlarmService();
  }, []);

  return !initialized 
    ? <>Loading...</> 
    : (
      <View style={styles.container}>
        {timeConfired ? 
          <MainTimerAlarm 
            soundService={alarmServiceRef.current} 
            setTime={setTime} 
            time={time} 
            timeInfo={timer} 
            stopped={!timeConfired} 
          /> 
          : <></>}
        <SetMainTimer setTimer={setTimerFunc} setCancel={setCancel} />
      </View>
    ); 
}

额外提示

你的服务类名存在拼写错误(SoundAlamarService → SoundAlarmService),建议统一修正,避免后续代码混淆。

内容的提问来源于stack exchange,提问作者pawelek91

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:40:42