Skip to content

Commit

Permalink
Merge pull request #21 from ChocolateLoverRaj/forward-ref
Browse files Browse the repository at this point in the history
forwardRef
  • Loading branch information
ChocolateLoverRaj authored Mar 16, 2023
2 parents d305c14 + 8da2200 commit 465979f
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 21 deletions.
9 changes: 7 additions & 2 deletions lib/reactObserver/RenderFn.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { FC } from 'react'
import { FC, ForwardedRef } from 'react'
import Observe from './Observe'
type RenderFn<P = {}> = (observe: Observe, props: P) => ReturnType<FC>

type RenderFn<Props = {}, Ref = never> = (
observe: Observe,
props: Props,
ref: ForwardedRef<Ref>
) => ReturnType<FC>

export default RenderFn
40 changes: 21 additions & 19 deletions lib/reactObserver/reactObserver.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import RenderFn from './RenderFn'
import { FC, useRef } from 'react'
import { forwardRef, useRef } from 'react'
import Observable from '../Observable'
import diff from 'set-diffs'
import useRerender from '@utilityjs/use-force-rerender'

const reactObserver = <P = {}>(renderFn: RenderFn<P>): FC<P> => (props) => {
const rerender = useRerender()
const previousObservablesRef = useRef(new Set<Observable<unknown>>())
const observables = new Set<Observable<unknown>>()
const returnValue = renderFn((observable) => {
observables.add(observable)
return observable.getValue()
}, props)
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const reactObserver = <Props = {}, Ref = never>(renderFn: RenderFn<Props, Ref>) =>
forwardRef<Ref, Props>((props, ref) => {
const rerender = useRerender()
const previousObservablesRef = useRef(new Set<Observable<unknown>>())
const observables = new Set<Observable<unknown>>()
const returnValue = renderFn((observable) => {
observables.add(observable)
return observable.getValue()
}, props, ref)

const { add, remove } = diff(previousObservablesRef.current, observables)
add.forEach(({ addRemove: { add } }) => {
add(rerender)
})
remove.forEach(({ addRemove: { remove } }) => {
remove(rerender)
})
previousObservablesRef.current = observables
const { add, remove } = diff(previousObservablesRef.current, observables)
add.forEach(({ addRemove: { add } }) => {
add(rerender)
})
remove.forEach(({ addRemove: { remove } }) => {
remove(rerender)
})
previousObservablesRef.current = observables

return returnValue
}
return returnValue
})

export default reactObserver

0 comments on commit 465979f

Please sign in to comment.