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

React Native TypeScript组件动态导入JSON文件报错求助

React Native + TypeScript 动态导入JSON文件报错解决方案

问题根源

React Native的Metro打包器依赖静态编译分析确定打包资源范围。你使用的完全动态导入import(../../../assets/data/topics/${reference})无法被Metro静态解析——打包器无法提前预判reference对应的具体文件,因此抛出Invalid call错误,哪怕路径实际正确。


解决方法

方法1:缩小动态导入范围(推荐)

将基础路径固定,仅保留子路径/文件名作为动态部分,让Metro能扫描到目标目录下的所有文件并提前打包。同时注意JSON模块的默认导入在module.default中:

import React, { useEffect, useState } from "react";
import { View, Text } from "react-native";
import styles from "./styles";

type Props = {
  reference: string; // 示例:units/top-1-sec-1-unit-1.json
};

type Block = {
  blockId: string;
  blockName: string;
};

const BlockComponent = ({ reference }: Props) => {
  const [unit, setUnit] = useState<Block[]>([]);

  useEffect(() => {
    const loadData = async () => {
      try {
        // 固定基础路径,动态部分为reference
        const module = await import(`../../../assets/data/topics/${reference}`);
        // JSON文件默认导出在module.default中
        setUnit(module.default);
      } catch (err) {
        console.error("加载数据失败:", err);
      }
    };

    loadData();
  }, [reference]);

  return (
    <View style={styles.container}>
      {unit.map((block) => (
        <View key={block.blockId} style={styles.blockBox}>
          <Text style={styles.boxText}>{block.blockName}</Text>
        </View>
      ))}
    </View>
  );
};

export default BlockComponent;

补充配置:如果Metro未自动识别JSON文件,在metro.config.js中添加:

module.exports = {
  resolver: {
    sourceExts: ['js', 'jsx', 'json', 'ts', 'tsx'],
  },
};

方法2:静态映射表(适合文件数量固定的场景)

提前导入所有可能用到的JSON文件,创建键为reference值的映射表,彻底规避动态导入问题:

import React, { useEffect, useState } from "react";
import { View, Text } from "react-native";
import styles from "./styles";

// 预导入所有JSON文件
import unit1 from "../../../assets/data/topics/units/top-1-sec-1-unit-1.json";
import unit2 from "../../../assets/data/topics/units/top-1-sec-1-unit-2.json";
// 按需添加更多文件...

type Props = {
  reference: string;
};

type Block = {
  blockId: string;
  blockName: string;
};

// 建立reference与对应数据的映射
const DATA_MAP: Record<string, Block[]> = {
  "units/top-1-sec-1-unit-1.json": unit1,
  "units/top-1-sec-1-unit-2.json": unit2,
};

const BlockComponent = ({ reference }: Props) => {
  const [unit, setUnit] = useState<Block[]>([]);

  useEffect(() => {
    const targetData = DATA_MAP[reference];
    if (targetData) {
      setUnit(targetData);
    } else {
      console.error("未找到对应reference的数据:", reference);
    }
  }, [reference]);

  return (
    <View style={styles.container}>
      {unit.map((block) => (
        <View key={block.blockId} style={styles.blockBox}>
          <Text style={styles.boxText}>{block.blockName}</Text>
        </View>
      ))}
    </View>
  );
};

export default BlockComponent;

这种方式性能稳定,适合JSON文件数量有限且不会频繁新增的场景。

方法3:通过Asset系统加载

利用React Native的Asset系统加载JSON资源,适合大量动态资源的场景:

  1. 配置react-native.config.js:
module.exports = {
  assets: ["./assets/data/topics/"],
};
  1. 执行资源链接(RN 0.60+可跳过,但建议执行):
npx react-native link
  1. 修改组件代码:
import React, { useEffect, useState } from "react";
import { View, Text, Asset } from "react-native";
import styles from "./styles";

type Props = {
  reference: string;
};

type Block = {
  blockId: string;
  blockName: string;
};

const BlockComponent = ({ reference }: Props) => {
  const [unit, setUnit] = useState<Block[]>([]);

  useEffect(() => {
    const loadData = async () => {
      try {
        const asset = Asset.fromModule(`../../../assets/data/topics/${reference}`);
        await asset.downloadAsync();
        const response = await fetch(asset.uri);
        const data = await response.json();
        setUnit(data);
      } catch (err) {
        console.error("加载数据失败:", err);
      }
    };

    loadData();
  }, [reference]);

  return (
    <View style={styles.container}>
      {unit.map((block) => (
        <View key={block.blockId} style={styles.blockBox}>
          <Text style={styles.boxText}>{block.blockName}</Text>
        </View>
      ))}
    </View>
  );
};

export default BlockComponent;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:19:58