Skip to content

Commit

Permalink
refactor(reactive-react): refactor observer function (#1523)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuweiGL authored May 31, 2021
1 parent 99a9cc3 commit 55b9342
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 33 deletions.
32 changes: 31 additions & 1 deletion packages/react/docs/api/shared/observer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,34 @@

## 描述

observer 是从[@formily/reactive-react](https://reactive.formilyjs.org)中导出的 observer,API 完全一致,这里不详细说明,使用 observer 主要是将组件支持响应式更新能力
observer 是一个 [HOC](https://reactjs.bootcss.com/docs/higher-order-components.html),用于为 react 函数组件添加 reactive 特性。

## 什么时候使用

当一个组件内部使用了 [observable](https://reactive.formilyjs.org/api/observable) 对象,而你希望组件响应 observable 对象的变化时。

## API 定义

```ts
interface IObserverOptions {
// 是否需要 observer 使用 forwardRef 传递 ref 属性
forwardRef?: boolean
scheduler?: (updater: () => void) => void
displayName?: string
}

function observer<P, Options extends IObserverOptions>(
component: React.FunctionComponent<P>,
options?: Options
): React.MemoExoticComponent<
React.FunctionComponent<
Options extends { forwardRef: true }
? React.PropsWithRef<P>
: React.PropsWithoutRef<P>
>
>
```

## 注意

`observer` 只能接收 callable 函数组件,不支持 `React.forwardRef` | `React.memo` 等包裹的组件。
51 changes: 19 additions & 32 deletions packages/reactive-react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,36 @@
import React, { memo, forwardRef, ForwardedRef } from 'react'
import React, { forwardRef, memo } from 'react'
import hoistNonReactStatics from 'hoist-non-react-statics'
import { useObserver } from './hooks'
import { IObserverOptions } from './types'

export function observer<P extends object>(
baseComponent: React.FunctionComponent<P>,
options?: IObserverOptions
): IObserverOptions extends { forwardRef: true }
? React.MemoExoticComponent<
React.ForwardRefExoticComponent<React.PropsWithoutRef<P>>
>
: React.MemoExoticComponent<React.FunctionComponent<P>>

export function observer<P extends object>(
baseComponent: React.FunctionComponent<P>,
options?: IObserverOptions
) {
export function observer<P, Options extends IObserverOptions>(
component: React.FunctionComponent<P>,
options?: Options
): React.MemoExoticComponent<
React.FunctionComponent<
Options extends { forwardRef: true }
? P & {
ref?: 'ref' extends keyof P ? P['ref'] : React.RefAttributes<any>
}
: React.PropsWithoutRef<P>
>
> {
const realOptions = {
forwardRef: false,
...options,
}

const wrappedComponent = realOptions.forwardRef
? forwardRef(
(
props: P,
ref: ForwardedRef<'ref' extends keyof P ? P['ref'] : any>
) => {
return useObserver(
() =>
baseComponent({
...props,
...ref,
}),
realOptions
)
}
)
: (props: P) => {
return useObserver(() => baseComponent(props), realOptions)
? forwardRef((props: any, ref: any) => {
return useObserver(() => component({ ...props, ref }), realOptions)
})
: (props: any) => {
return useObserver(() => component(props), realOptions)
}

const memoComponent = memo(wrappedComponent)

hoistNonReactStatics(memoComponent, baseComponent)
hoistNonReactStatics(memoComponent, component)

if (realOptions.displayName) {
memoComponent.displayName = realOptions.displayName
Expand Down

0 comments on commit 55b9342

Please sign in to comment.