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

React Native中如何在API请求URL中传递ID?

如何在React Native + Django项目中正确传递API请求的ID参数?

问题场景

我用React Native做前端、Django做后端开发应用时,遇到API参数传递问题:

  • 硬编码ID(比如http://192.168.1.68:8000/api/categories/${2}/)调用API完全正常;
  • 动态传入ID时,会触发错误:There was a problem with the fetch operation:, [Error: Network response was not ok];
  • 调整代码后又出现新错误:Invariant Violation: TaskQueue: Error with task : Tried to get frame for out of range index NaN。

现有代码

API请求函数

export const fetchSubCategoryData = async (id) => {
    try {
        const response = await fetch(`http://192.168.1.68:8000/api/categories/${id}/`, {
            method: "GET",
            headers: {
                Accept: "application/json",
                "Content-Type": "application/json",
            },
        });
        if (!response.ok) {
            throw new Error("Network response was not ok");
        }

        return await response.json();
    } catch (error) {
        console.error("There was a problem with the fetch operation:", error);
        throw error;
    }
};

最初的SubCategoryScreen组件

export const SubCategoryScreen = ({ route }) => {
    const [subCatgoryList, setSubCategoryList] = useState([]);

    useEffect(() => {
        fetchSubCategoryData(route.category).then((data) => {
            setSubCategoryList(data);
        });
    }, [route.category]);

    return (
        <SafeArea>
            <CategoryList
                data={subCatgoryList}
                renderItem={({ item }) => {
                    return (
                        <TouchableOpacity onPress={() => console.log(item)}>
                            <Spacer position="bottom" size="large">
                                <SubCategoryInfoCard category={item} />
                            </Spacer>
                        </TouchableOpacity>
                    );
                }}
                keyExtractor={(item) => item.id}
            />
        </SafeArea>
    );
};

CategoryScreen跳转组件

export const CategoryScreen = ({ navigation }) => {
    const { loading, error, categoryList } = useContext(CategoryContext);
    return (
        <SafeArea>
            {loading && (
                <LoadingContainer>
                    <ActivityIndicator animating={true} color={MD2Colors.green200} />
                </LoadingContainer>
            )}
            <Search />
            <CategoryList
                data={categoryList}
                renderItem={({ item }) => {
                    console.log(item.id);
                    return (
                        <TouchableOpacity
                            onPress={() => navigation.navigate("groepen", { subcategories: item.id })}>
                            <Spacer position="bottom" size="large">
                                <CategoryInfoCard category={item} />
                            </Spacer>
                        </TouchableOpacity>
                    );
                }}
                keyExtractor={(item) => item.id}
            />
        </SafeArea>
    );
};

问题根源分析

  1. 参数键名不匹配:CategoryScreen跳转时传递的参数键是subcategories,但SubCategoryScreen里读取的是route.category,导致传入API的ID是undefined,请求URL变成/api/categories/undefined/,后端返回404错误,触发Network response was not ok。
  2. 缺少参数校验:没有对传入的ID做有效性判断,空值或非数值ID直接发起请求,导致无效请求。
  3. 列表渲染数据异常:调整代码后可能导致subCatgoryList不是有效数组,或者item.id为NaN,引发列表渲染时的索引错误。

解决方案

1. 修正参数传递的键名

保持跳转和接收的参数键名一致,二选一修改:

  • 修改CategoryScreen的跳转代码:将参数键改为category
onPress={() => navigation.navigate("groepen", { category: item.id })}
  • 或者修改SubCategoryScreen的参数读取:读取route.params.subcategories
useEffect(() => {
    fetchSubCategoryData(route.params.subcategories).then((data) => {
        setSubCategoryList(data);
    });
}, [route.params.subcategories]);

2. 增加参数校验与错误处理

修改API请求函数,校验ID有效性并抛出详细错误

export const fetchSubCategoryData = async (id) => {
    // 转换为数值并校验有效性
    const numericId = Number(id);
    if (isNaN(numericId) || numericId <= 0) {
        throw new Error('无效的分类ID');
    }
    try {
        const response = await fetch(`http://192.168.1.68:8000/api/categories/${numericId}/`, {
            method: "GET",
            headers: {
                Accept: "application/json",
                "Content-Type": "application/json",
            },
        });
        if (!response.ok) {
            // 获取后端返回的错误详情,方便调试
            const errorText = await response.text();
            throw new Error(`请求失败,状态码:${response.status},详情:${errorText}`);
        }

        return await response.json();
    } catch (error) {
        console.error("获取子分类数据失败:", error);
        throw error;
    }
};

修改SubCategoryScreen,增加空值判断与数据容错

export const SubCategoryScreen = ({ route }) => {
    const [subCatgoryList, setSubCategoryList] = useState([]);
    // 使用可选链避免参数不存在时报错
    const categoryId = route.params?.category;

    useEffect(() => {
        // 空ID不发起请求
        if (!categoryId) return;
        
        fetchSubCategoryData(categoryId)
            .then((data) => {
                // 确保数据是数组,避免渲染错误
                setSubCategoryList(Array.isArray(data) ? data : []);
            })
            .catch(err => {
                console.error('加载子分类失败:', err);
                setSubCategoryList([]);
            });
    }, [categoryId]);

    return (
        <SafeArea>
            {/* 数据为空时显示提示,避免空列表渲染问题 */}
            {subCatgoryList.length === 0 ? (
                <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
                    <Text>暂无子分类数据</Text>
                </View>
            ) : (
                <CategoryList
                    data={subCatgoryList}
                    renderItem={({ item }) => (
                        <TouchableOpacity onPress={() => console.log(item)}>
                            <Spacer position="bottom" size="large">
                                <SubCategoryInfoCard category={item} />
                            </Spacer>
                        </TouchableOpacity>
                    )}
                    // 将ID转为字符串,避免数值型ID可能引发的NaN问题
                    keyExtractor={(item) => String(item.id)}
                />
            )}
        </SafeArea>
    );
};

3. 调试技巧

  • 在fetchSubCategoryData里打印最终请求的URL,确认ID是否正确拼接:
    console.log('请求URL:', `http://192.168.1.68:8000/api/categories/${numericId}/`);
    
  • 查看Django后端的日志,确认接收到的请求路径是否正确,排查后端是否返回预期状态码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:58:20