所有分类
  • 所有分类
  • 后端开发

React:如何使用 RxJS 去优化数据流

React:如何使用 RxJS 优化数据流。

现在我们熟悉使用它 functional component 和 hooks 来处理 react 逻辑。熟悉 Angular 用户可能更熟悉 RxJS 处理异步和数据状态。让我们看看。 React 中使用 RxJS 会有什么优势吗?

一般来说,处理组件中的数据流只有三种情况:

  • Component 中 props 的变化

  • 用户在界面上操作,触发 event 修改 component 的数据

  • Component 中监听的 store 触发数据变化

让我们看一个非常简单的例子:

image.png

有一个 component,显示 input 中输入的数据。逻辑也很简单:

export function ShowInput(props: { data: string; }): JSX.Element {
  return <>{props.data}</>;
}

也就是第一种情况,component 状态是通过的,props 传进来的。

当然,当数据发生变化时,这是没有问题的。假设我们每次输入都会触发一次 api call,然后把 api 在界面上显示返回的内容。这里有两个问题需要处理:

  • 尽可能减少 api call 例如,用户输入的次数 500ms 当上述停顿时,我们认为用户在开始之前已经结束了输入 call api)

  • 如果用户输入多次,就会有多次 api call,那么后面 api 返回的数据应该永远覆盖前面 api 返回的数据。

  • 暂时不考虑 api 可能会出错,需要重新出错 call api 的情况

熟悉 RxJS 要知道,这是一个非常简单的数据流问题,如果我们把它放在一边 props 如果将数据视为数据流,则可以非常简单地解决。

const apiRespons$ = data$.pipe(
  debounceTime(500),
  switchMap(data => getApiResponse(data)),
);
// Mock API call
function getApiResponse(data: string) {
  return of(data   ' data from api').pipe(delay(1000));
}

那么,问题来了,怎么会呢? props data 转换成 stream, 如何完成处理? stream 转换成 component state 呢。

这里需要引入一个库: rxjs-hooks

用法一: 将 stream 转换为 componet state.

例如,我们已经得到了它 apiResponse$,如何在 component 显示在中间的?

const apiRespons$ = data$.pipe(
  debounceTime(500),
  switchMap(data => getApiResponse(data)),
);
const apiResponse = useObservable(() => apiRespons$);

那怎样结合呢? props 用什么变化?

用法二: 将 props 转换为 stream useObservable 还可以输入两个参数:

  • 状态的初始值 (类似,useState)

  • 监控变量(类似) useEffect 将数组参数转换为 stream 作为函数的参数

完整的代码会变成这样:

export function ShowInput(props: { data: string; }): JSX.Element {
  const apiResponse = useObservable((_, input$) => input$.pipe(
    debounceTime(500),
    switchMap(([data]) => getApiResponse(data)),
  ), '', [props.data]);
  return <>{apiResponse}</>;
}

当然,当数据发生变化时,也有可能是当前的 component 的,不是 props 传进来的。也就是说这个。 input 也许是现在 component 中。

当然,我们简单地把它放在一边 input 放在当前的 componnet 监听内容从中 props 换成 state. 也比较简单。

const [data, setData] = useState<string>();
const apiResponse = useObservable((_, input$) => input$.pipe(
  debounceTime(500),
  switchMap(([inputData]) => getApiResponse(inputData || '')),
), '', [data]);

那有没有更简单的方法呢?

涉及用法三:将 event 函数的调用自动转换为 stream

const [onInputChange, apiResponse] = useEventCallback((data$: Observable<string>) => data$.pipe(
  debounceTime(500),
  switchMap((data) => getApiResponse(data || '')),
), '');

那有没有更简单的方法呢?

涉及用法三:将 event 函数的调用自动转换为 stream

const [onInputChange, apiResponse] = useEventCallback((data$: Observable<string>) => data$.pipe(
  debounceTime(500),
  switchMap((data) => getApiResponse(data || '')),
), '');

这就将 useState 和 useObservable 一体化。第一个参数时。 event 函数,第二个参数 state。

当然,如果有用的话 redux observable 如果是的话,可以很好的跟着 rxjs-hooks 合为一体。

那么,问题是,使用数据流来处理数据有什么好处呢?

  • RxJS 处理数据流的方法很多,可以大大简化我们处理数据的过程。类似于异步 lodash.

  • 在 React 我们经常同时使用它 Redux 和 Hooks, 在某种程度上,我们将使用它 Redux 处理全局或大状态管理,hooks 处理 component 层,或小数据状态管理。使用 redux observable 和 rxjs hooks 这是一种很好的沟通全局和局部状态的方式。

  • 我们直到 redux 时跨平台。但有时我们不想把所有的数据状态都封装在一起 redux 中。若要实现数据状态的跨平台,则无需使用 redux 的话,rxjs 关闭一个状态的工具无非是最简单的。因为一个 subject 就是最简单的一个 store. 多平台共享的最佳方式是让我们的主要逻辑不依赖框架。

对于 component 逻辑共享层的局部状态:

react   angular  
|       /
hooks  component store
|      /
js rxjs store

对于 redux 状态共享

react     angular
|         /
redux observable

原文链接:https://www.icz.com/technicalinformation/web/seo/2023/05/9415.html,转载请注明出处~~~
0
注意:请收藏好网址www.icz.com,防止失联!站内免费资源持续上传中…!赞助我们
显示验证码
没有账号?注册  忘记密码?