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

React TypeScript:如何将FunctionComponent作为属性传递给另一个组件

问题根源分析

两个警告的核心原因:

  1. 状态更新时机错误:Robots组件直接在函数体中调用SetInterval,每次组件渲染都会执行这段逻辑,导致渲染过程中触发setRobotArray,违反了React render方法必须是纯函数的规则。
  2. 组件渲染方式错误:BasicBlocks中直接将content(一个FunctionComponent)作为React子元素输出,React无法直接渲染函数,必须将其实例化为组件实例。

解决方案

1. 修复BasicBlocks组件(解决组件渲染警告)

调整content的类型定义,并正确实例化组件:

import React from "react";
import BlockStyle from "../styleDefs/blocks.module.css";

interface BasicBlocksProps {
  title?: string;
  subtitle?: string;
  // 改用ElementType兼容函数/类组件,提升通用性
  content?: React.ElementType;
  // 用联合类型约束size,增强类型安全性
  size: "large" | "medium" | "small";
  center: boolean;
}

const BasicBlocks: React.FunctionComponent<BasicBlocksProps> = ({ 
  title, 
  subtitle, 
  content: Content, // 重命名为大写开头,符合React组件命名规范
  size, 
  center 
}) => {
  return (
    <div className={
      size === "large" ? BlockStyle.large :
      size === "medium" ? BlockStyle.medium : BlockStyle.small
    }>
      {title && <h1 className={center ? BlockStyle.titleCenter : BlockStyle.titleLeft}>{title}</h1>}
      {subtitle && <div className={center ? BlockStyle.subtitleCenter : BlockStyle.subtitleLeft}>{subtitle}</div>}
      {/* 实例化组件,而非直接输出函数 */}
      <div className={BlockStyle.content}>{Content && <Content />}</div>
    </div>
  );
};

export default BasicBlocks;

2. 修复Robots组件(解决状态更新时机警告)

用useEffect包裹定时器逻辑,确保仅在组件挂载时初始化一次:

import React, { useState, useEffect } from "react";
import axios from "axios";
import TableStyle from "../styleDefs/tableStyles.module.css";
import ButtonStyle from "../styleDefs/buttons.module.css";
import { basicBlock2 } from "../styleDefs/styles";
import BasicBlocks from "./basicBlocks";

interface Robot {
  robot_name: string;
  connected: boolean;
  battery: number;
  active_user_id: number;
  active_user_first: string;
  active_user_last: string;
  robot_type: "simple" | "lilflo";
}

const Robots: React.FunctionComponent = () => {
  const [robotArray, setRobotArray] = useState<Array<Robot>>([]);

  // 用useEffect包裹定时器,避免重复创建
  useEffect(() => {
    const interval = SetInterval(() => {
      axios
        .get("/api/robots/")
        .then((res) => {
          setRobotArray(res.data.robots as Array<Robot>);
        })
        .catch((err) => {
          console.log("error fetching array of robots: " + err);
        });
    }, 1000 * 1);

    // 组件卸载时清除定时器,防止内存泄漏
    return () => clearInterval(interval);
  }, []); // 空依赖数组,仅在挂载/卸载时执行

  const robotRows = robotArray.map((robot) => {
    const hasBattery = robot["battery"] !== null;
    return (
      <tr key={robot.robot_name}>
        <td>{robot["robot_name"]}</td>
        <td>{robot["connected"].toString()}</td>
        <td>{hasBattery ? robot.battery : "Not Available"}</td>
        <td>{robot["active_user_first"] || "None"}</td>
      </tr>
    );
  });

  const RobotsPage: React.FunctionComponent = () => {
    return (
      <div style={basicBlock2}>
        <table className={TableStyle.table}>
          <thead>
            <tr>
              <th className={TableStyle.tableHead}>Robot Name</th>
              <th className={TableStyle.tableHead}>Connected</th>
              <th className={TableStyle.tableHead}>Battery</th>
              <th className={TableStyle.tableHead}>Active User</th>
            </tr>
          </thead>
          <tbody>{robotRows}</tbody>
        </table>
        <div className={ButtonStyle.buttonWrapperCenter}>
          <button className={ButtonStyle.addButton}>
            add robot
          </button>
        </div>
      </div>
    );
  };

  return (
    <BasicBlocks 
      title="Robot List" 
      subtitle="suck it" 
      size="large" 
      center={false} 
      content={RobotsPage} 
    />
  );
};

export default Robots;

额外优化说明

  • 类型约束:使用TypeScript联合类型限制size和robot_type的取值范围,避免无意义的字符串输入。
  • 内存泄漏防护:添加定时器清理逻辑,避免组件卸载后定时器继续运行。
  • 逻辑修正:调整hasBattery的判断逻辑,确保电池值为空时显示正确的提示文本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 08:35:07