网站搜索

javascript - 在 React 组件中使用自定义 API 客户端的惯用方法是什么?


我的前端应用包含一个 ApiClient 类,它隐藏了与我的服务器进行 HTTP 通信的细节。这是一个简单的 TypeScript 类,带有一个作为私有字段的 axios 客户端。

我在是否在根组件初始化客户端并将其传递给一些子组件上感到疑惑。

此刻我在根组件中以构造函数的简单 js 字段方式初始化我的客户端:

constructor() {
  super()
  ... // init state here 

  ... // some initializations like this.handler = this.handler.bind(this)

  this.apiClient = new ApiClient()
}

有些子组件也依赖于 apiClient(例如,登录组件应该向登录端点发送请求,editModal 组件通过 ID 发送请求以更新实体)。现在我将 apiClient 作为 props 传递:

<Login show={this.state.show}
                       handleModalClose={this.handleModalClose}
                       handleSuccessfulLogin={this.handleSuccessfulLogin}
                       httpClient={this.apiClient}
                /> }
...

<EditModal
                    httpClient={this.apiClient}
                    ...
                />

将它传递给组件的惯用方式是什么?把 client 作为 props 传递正确吗?如果我正确理解 React 文档的话,props 和 state 是用于渲染的,这对我来说有点困惑

答案#1

如果你的 API 客户端不依赖组件的任何属性/状态,最好的方式是单独初始化它,然后在需要使用它的文件中导入即可:

// apiClient.js

export const apiClient = new ApiClient();

// component.js 

import {apiClient} from '../apiClient';

如果你需要在组件内部处理登录/注销,并在 API 客户端中设置 token,你可以添加 login 和 logout 方法,这些方法将在客户端初始化后被调用。由于你的应用中只有一个客户端实例,这些更改(登录和注销)将在所有使用该客户端的组件中生效:

// Client.js
class ApiClient {
  constructor() {
    // do intance init stuff if needed
    this.token = null;
  }

  login(token) {
    this.token = token;
  }

  logout() {
    this.token = null;
  }
}


// apiClient.js

export const apiClient = new ApiClient();

// component.js 

import { apiClient } from '../apiClient';

const LoginPage = props => {

  const handleLogin = () => {
    const token = // get the token

      apiClient.login(token);
  }
}


// anotherComponent.js
const User = props => {
  useEffect(() => {
    apiClient.getUser()
  }, [])
}