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> ); };
问题根源分析
- 参数键名不匹配:CategoryScreen跳转时传递的参数键是
subcategories,但SubCategoryScreen里读取的是route.category,导致传入API的ID是undefined,请求URL变成/api/categories/undefined/,后端返回404错误,触发Network response was not ok。 - 缺少参数校验:没有对传入的ID做有效性判断,空值或非数值ID直接发起请求,导致无效请求。
- 列表渲染数据异常:调整代码后可能导致
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
相关产品推荐
相关产品推荐

