前言
在 React Native App 开发中,列表渲染 和网络请求是两个最基础、高频的能力。 本篇文章一次性带你走完完整流程:
-
使用
map遍历数组渲染列表,理解key的作用 -
启动本地 Node 后端 API(SQLite + Prisma,配套示例 JSON 返回样例,无需依赖外部在线接口服务)
-
RN 使用原生
fetch请求后端接口,展示真实数据 -
踩坑:Android 模拟器、真机调试网络问题
一、基础:map 遍历渲染列表
在useState里定义的数据,在很多时候,都是读取的接口数据,然后遍历出来,显示到页面上。
没有学如何读取接口之前,可以先定义一点假数据,然后遍历一下试试。 开发 App 列表,我们经常会拿到后端返回的数组,然后循环渲染每一项。在 React / RN 中,标准写法就是数组的 .map()。
1.1 定义状态数组
用 useState 定义课程假数据,每个对象包含唯一 id 和课程名称。
jsx
import { StyleSheet, Text, View } from 'react-native';
import { useState } from 'react';
export default function App() {
const [courses, setCourses] = useState([
{ id: 1, name: 'HTML' },
{ id: 2, name: 'CSS' },
{ id: 3, name: 'JavaScript' },
{ id: 4, name: 'React' },
{ id: 5, name: 'React Native' },
{ id: 6, name: 'Node.js' },
{ id: 7, name: 'Express' },
{ id: 8, name: 'MySQL' },
{ id: 9, name: 'Ruby On Rails' },
{ id: 10, name: 'Python' },
{ id: 11, name: 'Django' },
{ id: 12, name: 'C#' },
]);
return (
<View style={styles.container}>
{courses.map((course) => (
<Text key={course.id}>
{course.name}
</Text>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
1.2 核心要点
-
{}在 JSX 中用来嵌入 JS 表达式 -
.map()遍历数组,返回新的 JSX 元素数组,完成渲染 -
key 属性必须加
-
key 作用:帮助 React 识别列表每一个元素,高效做 Diff 更新
-
要求:列表内唯一,优先使用后端返回 id,不要直接用数组下标(简单演示可以,但生产不推荐)
-
不写 key:控制台会抛出警告,列表更新时容易出现渲染错乱
-
现在我们渲染的是前端写死的假数据,接下来搭建后端,拿到真实接口数据。
二、搭建并启动本地后端 API 服务
我们使用 Node + Prisma + SQLite 作为本地后端,SQLite 是文件型数据库,不用安装 MySQL、Docker,开箱即用。
2.1 后端源码准备
下载示例后端源码包 zxj‑api 解压。
建议把后端项目
zxj‑api和 RN 项目zxj‑app放在同一级目录。
2.2 安装依赖(可选切换淘宝镜像)
为了防止由于网络问题,导致依赖包安装出错。未使用 npm 中国镜像的,请先切换到中国镜像。
bash
# 可选:安装 nrm 切换淘宝镜像,解决国内 npm 下载慢
npm i -g nrm
nrm use taobao
# 进入后端项目目录
cd zxj-api
# 安装项目依赖
npm i
2.3 初始化 Prisma 数据库客户端
bash
npx prisma generate
2.4 启动后端服务
bash
npm start
启动成功后,本地接口基础地址:http://localhost:3000
⚠️ 启动后端的终端窗口不要关闭,关闭接口服务就停止了。
2.5 数据库管理
项目使用 SQLite,数据库文件:prisma/dev.db 接口项目的数据库,我使用了SQLite来开发。它其实就是一个本地文件。 用这种数据库,就不需要大家去安装配置Docker,搭建MySQL运行环境,导入数据库了。
数据库的管理,有两种方法:
- Prisma Studio(网页版) 新开终端,进入 zxj‑api:
bash
# 默认端口
npx prisma studio
# 如果端口5555冲突(Android模拟器占用),更换端口
npx prisma studio -p 5556
浏览器自动打开可视化数据库面板,可以直接增删改查。
- Navicat 连接 SQLite
官方免费版本下载地址:www.navicat.com.cn/download/na... Navicat Premium Lite(免费版)新建 SQLite 连接,选中项目内 prisma/dev.db 文件即可。
2.6 接口说明 & 返回 JSON 样例
① 首页接口 GET /
-
请求参数:无
-
响应格式:
200 application/json返回包含三类课程数组:recommendedCourses(推荐课程)、likesCourses(热门课程)、introductoryCourses(入门课程)。
json
{
"status": true,
"message": "查询首页数据成功。",
"data": {
"recommendedCourses": [
{
"id": 10,
"name": "React Native + Expo 项目实战",
"image": "http://localhost:3000/uploads/images/demo.png",
"recommended": true,
"introductory": false,
"likesCount": 0,
"chaptersCount": 0,
"category": {"id":3,"name":"移动端开发"}
}
],
"likesCourses": [],
"introductoryCourses": []
}
}
② 搜索接口 GET /search
-
Query 参数:
q(可选,课程名关键词,不传返回全部课程) -
浏览器直接访问测试:
http://localhost:3000/search -
返回结构:
{status: true, data: {courses: [...]}}
三、RN 使用 Fetch 请求后端接口
React Native 内置 Fetch API,不需要额外安装 axios 等网络库,就可以发起网络请求。
3.1 完整代码
jsx
import { Button, StyleSheet, Text, View } from 'react-native';
import { useState } from 'react';
export default function App() {
// 初始为空数组,等待接口填充数据
const [courses, setCourses] = useState([]);
/**
* 获取课程接口数据
* @returns {Promise<void>}
*/
const fetchData = async () => {
// ⚠️ Android模拟器 / 真机不能写 localhost,需要替换成电脑局域网IP
const res = await fetch('http://localhost:3000/search');
const { data } = await res.json();
setCourses(data.courses);
console.log('获取到的数据是:', data.courses);
};
return (
<View style={styles.container}>
{courses.map((course) => (
<Text key={course.id}>
{course.name}
</Text>
))}
<Button title='获取课程' onPress={fetchData}/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});

- 函数的名字,叫做
fetchData。 - 接口读取,是一个异步请求,所以别忘了要加上
async。 - 里面就用
fetch来请求接口地址了,当然,前面别忘记了加上await。 - 获取到的数据是
JSON格式的,这里要用.json()来解析一下。 - 大家观察返回的数据格式
{ data: { courses: [...] } },它里面是有一层data,在data里面才是最后的课程数据。 - 所以,可以给
data加了一个大括号,直接将data解构出来。 - 最后将获取到的
data.courses课程数据,使用setCourses设置到课程状态里。
四、重点踩坑:Android 模拟器 & 真机网络
这是 RN 本地开发最容易踩的坑!
4.1 Android 模拟器
模拟器里的 localhost 指向模拟器本身,不是你的电脑,接口访问失败。 ✅ 解决方案:把地址改成电脑局域网 IP
bash
# Windows 查看局域网IPv4
ipconfig | findstr "IPv4"
# macOS
ifconfig | grep "inet " | grep -v 127.0.0.1
示例,拿到 IP:192.168.31.100
js
const res = await fetch('http://192.168.31.100:3000/search');
4.2 手机真机扫码预览
手机和电脑必须连同一个路由器 / Wi‑Fi 。 同样不能使用 localhost,替换为电脑局域网 IP。 修改代码后,摇一摇手机,选择 Reload 重新加载 App。
Windows 电脑访问仍然失败:检查并临时关闭防火墙,手机浏览器先访问
http://你的IP:3000验证接口通不通。 IP 会随网络重启变化,每次换环境需要重新查看 IP。
五、接口调试方法
-
console.log打印数据,在 RN 启动终端查看日志 -
终端按
j打开 Expo JS 调试器,在 Console 面板查看返回数据
注意:Expo SDK 54+ Windows、SDK56 全平台,调试器 Network 面板无法查看网络请求,属于 Expo 已知问题,不影响开发,使用 Console 打印调试即可。
七、总结
-
JSX 列表渲染:数组
.map(),必须携带唯一 key; -
后端服务:Node + Prisma SQLite,启动三步:
npm i→npx prisma generate→npm start; -
RN 网络请求:原生 Fetch API,搭配 async/await,
.json()解析响应; -
网络大坑:模拟器 / 真机不能用 localhost,改用电脑局域网 IP,手机电脑同一局域网;
完整链路:后端接口服务启动 → RN 点击按钮 fetch 请求 → state 更新 → map 渲染列表。这就是移动端前后端联调最基础的完整闭环。