-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…or-hot-reloading-with-assertandunwraprefs #249 Create validateAndUnwrapRefs function
- Loading branch information
Showing
5 changed files
with
123 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
src/hooks/useRefs/utils/validateAndUnwrapRefs/validateAndUnwrapRefs.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { Meta } from '@storybook/blocks'; | ||
|
||
<Meta title="hooks/useRefs/utils/validateAndUnwrapRefs" /> | ||
|
||
# validateAndUnwrapRefs | ||
|
||
Utility to validate and unwrap RefObjects in an object | ||
|
||
## Reference | ||
|
||
```ts | ||
export function validateAndUnwrapRefs<T extends Refs>(refs: T): NonNullableRecord<UnwrapRefs<T>>; | ||
``` | ||
|
||
### Returns | ||
|
||
Object with NonNullable unwrapped RefObjects | ||
|
||
## Usage | ||
|
||
```tsx | ||
type DemoComponentRefs = Refs<{ | ||
heading: HTMLHeadingElement; | ||
buttons: Array<HTMLButtonElement | null>; | ||
}>; | ||
|
||
function DemoComponent() { | ||
const refs = useRefs<DemoComponentRefs>(); | ||
|
||
const onClick = useCallback(() => { | ||
const [isValid, { heading, buttons }] = validateAndUnwrapRefs(refs); | ||
|
||
if (isValid) { | ||
return; | ||
} | ||
|
||
console.log(heading); // HTMLHeadingElement | ||
console.log(buttons); // Array<HTMLButtonElement | null> | ||
}, [refs]); | ||
|
||
return ( | ||
<> | ||
<h1 ref={refs.heading}>{heading}</h1> | ||
|
||
{items.map((item, index) => ( | ||
<button key={item} ref={arrayRef(refs.buttons, index)} onClick={onClick}> | ||
{item} | ||
</button> | ||
))} | ||
</> | ||
); | ||
} | ||
``` |
41 changes: 41 additions & 0 deletions
41
src/hooks/useRefs/utils/validateAndUnwrapRefs/validateAndUnwrapRefs.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { renderHook } from '@testing-library/react'; | ||
import { describe, expect, it } from 'vitest'; | ||
import { useRefs } from '../../useRefs.js'; | ||
import type { MutableRefs } from '../../useRefs.types.js'; | ||
import { validateAndUnwrapRefs } from './validateAndUnwrapRefs.js'; | ||
|
||
type TestRefs = MutableRefs<{ | ||
item1: string; | ||
item2: number; | ||
}>; | ||
|
||
describe('unwrapRefs', () => { | ||
it('should be invalid when ref object contains null field', () => { | ||
const { result } = renderHook(() => useRefs<TestRefs>()); | ||
|
||
result.current.item1.current = null; | ||
result.current.item2.current = 2; | ||
|
||
expect(validateAndUnwrapRefs(result.current)).toEqual([false, undefined]); | ||
}); | ||
|
||
it('should be invalid when ref object contains undefined field', () => { | ||
const { result } = renderHook(() => useRefs<TestRefs>()); | ||
|
||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-expect-error | ||
result.current.item1.current = undefined; | ||
result.current.item2.current = 2; | ||
|
||
expect(validateAndUnwrapRefs(result.current)).toEqual([false, undefined]); | ||
}); | ||
|
||
it("should be valid when ref object doesn't contain null value", () => { | ||
const { result } = renderHook(() => useRefs<TestRefs>()); | ||
|
||
result.current.item1.current = 'test'; | ||
result.current.item2.current = 2; | ||
|
||
expect(validateAndUnwrapRefs(result.current)).toEqual([true, { item1: 'test', item2: 2 }]); | ||
}); | ||
}); |
26 changes: 26 additions & 0 deletions
26
src/hooks/useRefs/utils/validateAndUnwrapRefs/validateAndUnwrapRefs.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { | ||
isNonNullableRecord, | ||
type NonNullableRecord, | ||
} from '../../../../_utils/isNonNullableRecord/isNonNullableRecord.js'; | ||
import type { Refs } from '../../useRefs.types.js'; | ||
import { unwrapRefs } from '../unwrapRefs/unwrapRefs.js'; | ||
import type { UnwrapRefs } from '../unwrapRefs/unwrapRefs.types.js'; | ||
|
||
/** | ||
* Unwraps refs and assert every field is not null | ||
* | ||
* NOTE: this function asserts fields known during runtime on the refs parameter. | ||
* The useRefs Proxy only creates a field in the getter, this means that a field's | ||
* value will still be undefined when you never reference that field. The return | ||
* type of this function doesn't reflect that behavior. | ||
*/ | ||
export function validateAndUnwrapRefs<T extends Refs>( | ||
refs: T, | ||
): [false, undefined] | [true, NonNullableRecord<UnwrapRefs<T>>] { | ||
const unwrappedRefs = unwrapRefs(refs); | ||
if (!isNonNullableRecord(unwrappedRefs)) { | ||
return [false, undefined]; | ||
} | ||
|
||
return [true, unwrappedRefs]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters