【React Native】环境变量和封装 fetch

发布于:2025-07-16 ⋅ 阅读:(18) ⋅ 点赞:(0)

环境变量和封装fetch

环境变量

一般做开发,都会将接口地址配置到环境变量里。在Expo建的项目里,也可以使用环境变量

在项目根目录新建一个.env文件,里面添加上:

EXPO_PUBLIC_API_URL=http://localhost:3000

如果你用手机真机等局域网设备访问,就改成电脑的IP地址,例如:

EXPO_PUBLIC_API_URL=http://192.168.x.xx:3000

Expo里:

  • 环境变量的命名,全部要大写。
  • 而且必须以EXPO_PUBLIC开头,后面再自己添加其他的。

安装 urlcat

封装请求文件之前,先去安装下urlcat包:

npm i urlcat

利用它,可以非常简单的拼接URL路径和查询参数。要不然就得自己很麻烦的处理URL路径里的?号和&符号。

例如传这些参数进去:

urlcat('http://localhost:3000', '/articles', { page: 1, limit: 10 })

它就会自动转换成:

http://localhost:3000/articles?page=1&limit=10

封装 request

  • headers里,告诉接口,返回的数据格式是JSON,发送的数据格式也是JSON
  • config里,将各种参数都丢进去。根据React Native官方文档里的Fetch API 说明,传给接口的数据,要将JavaScript对象转为JSON字符串。
import urlcat from "urlcat";

/**
 * 基础请求函数
 * @param { string } url - API 请求路径(如 '/articles')
 * @param { object } [options] - 请求配置项
 * @param { string } [options.method='GET'] - HTTP 方法
 * @param { object } [options.params] - URL 查询参数(如 { page: 1, limit: 10 })
 * @param { object } [options.body] - 请求体数据
 * @returns { Promise<object> } 返回解析后的JSON数据
 *
 * @example
 * // 基础调用示例
 * request('/articles').then(data => console.log(data))
 *
 * @example
 * // 带查询参数的 GET 请求
 * request('/articles', {
 *   params: { page: 1, limit: 10 }
 * })
 *
 * @example
 * // POST 请求
 * // 提交表单数据
 * request('/auth/sign_in', {
 *   method: 'POST',
 *   body: { login: 'user', password: '123123' }
 * })
 */
const request = async (url, { method = "GET", params, body } = {}) => {
  // 完整的接口地址
  const apiUrl = process.env.EXPO_PUBLIC_API_URL;
  const requestUrl = urlcat(apiUrl, url, params);

  // 请求头
  const headers = {
    Accept: "application/json",
    "Content-Type": "application/json",
    // 待完成:传递 token
  };

  const config = {
    method,
    headers,
    ...(body && { body: JSON.stringify(body) }),
  };

  const response = await fetch(requestUrl, config);

  if (!response.ok) {
    // 待完成:登录超时处理

    const { message, errors } = await response.json().catch(() => null);
    const error = new Error(message);
    error.status = response.status;
    error.errors = errors;
    throw error;
  }

  return await response.json();
};

/**
 * GET 请求
 * @param { string } url - 请求地址
 * @param { object } [params] - 查询参数
 * @returns { Promise<any> } 返回解析后的JSON数据
 *
 * @example
 * // 基本 GET 请求
 * get('/articles').then(data => console.log(data))
 *
 * @example
 * // 带查询参数的 GET 请求
 * get('/articles', { page: 1, limit: 10 })
 */
export const get = (url, params) => request(url, { method: "GET", params });

/**
 * POST 请求
 * @param { string } url - 请求地址
 * @param { object } body - 请求体数据
 * @returns { Promise<any> } 返回解析后的 JSON 数据
 *
 * @example
 * // 提交表单数据
 * post('/auth/sign_in', { login: 'user', password: '123123' })
 */
export const post = (url, body) => request(url, { method: "POST", body });

/**
 * PUT 请求
 * @param { string } url - 请求地址
 * @param { object } body - 请求体数据
 * @returns { Promise<any> } 返回解析后的 JSON 数据
 *
 * @example
 * // 更新数据
 * put('/users/info', { nickname: 'clwy', company: '长乐未央公司' })
 */
export const put = (url, body) => request(url, { method: "PUT", body });

/**
 * PATCH 请求
 * @param { string } url - 请求地址
 * @param { object } body - 请求体数据
 * @returns { Promise<any> } 返回解析后的 JSON 数据
 *
 * @example
 * // 部分更新数据
 * 注意:本项目无任何接口使用 PATCH
 */
export const patch = (url, body) => request(url, { method: "PATCH", body });

/**
 * DELETE 请求
 * @param { string } url - 请求地址
 * @returns { Promise<any> } 返回解析后的 JSON 数据
 *
 * @example
 * // 注销用户
 * del('/users/me')
 */
export const del = (url) => request(url, { method: "DELETE" });

export default request;
// const res = await fetch(`http://192.168.1.138/search?q=${keyword}`);
// const res = await request("/search", { params: { q: keyword } });
const res = await get("/search", { q: keyword });
  // 当依赖参数是一个对象或引用类型,例如 params,
  // 即使它的内容没有变化,每次组件重新渲染时它的引用都会不同。
  // 从而导致 useEffect 不断触发,会造成无限循环请求。
  // 可以使用 JSON.stringify(params) 转换为字符串,来解决这个问题。
  useEffect(() => {
    fetchData();
  }, [url, JSON.stringify(params)]);

网站公告

今日签到

点亮在社区的每一天
去签到