Skip to content

Commit 54f334a

Browse files
authored
New Unwrap and Times helper components (#157)
1 parent e87007a commit 54f334a

File tree

5 files changed

+92
-0
lines changed

5 files changed

+92
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { render } from '@react-facet/dom-fiber-testing-library'
2+
import { createFacet } from '../facet'
3+
import React from 'react'
4+
import { Times } from './Times'
5+
6+
it('renders the child n times, passing the index', () => {
7+
const mockFacet = createFacet({ initialValue: 3 })
8+
const result = render(<Times count={mockFacet}>{(index) => <>{index}</>}</Times>)
9+
10+
// Has all the indexes, proving it looped and rendered all the children
11+
expect(result.container).toHaveTextContent('012')
12+
})
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React, { ReactElement } from 'react'
2+
import { Facet } from '../types'
3+
import { Unwrap } from './Unwrap'
4+
5+
/**
6+
* Given a facet with a number, it renders its children "count" times.
7+
*
8+
* @param count facet with the amount of items to render
9+
* @param children function that will be called passing an index and the total.
10+
*/
11+
export const Times = ({
12+
count,
13+
children,
14+
}: {
15+
count: Facet<number>
16+
children: (index: number, count: number) => ReactElement | null
17+
}) => {
18+
return (
19+
<Unwrap data={count}>
20+
{(count) => {
21+
const array = new Array(count)
22+
23+
for (let index = 0; index < count; index++) {
24+
array[index] = <React.Fragment key={index}>{children(index, count)}</React.Fragment>
25+
}
26+
27+
return <>{array}</>
28+
}}
29+
</Unwrap>
30+
)
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react'
2+
import { render, screen } from '@react-facet/dom-fiber-testing-library'
3+
import { createFacet } from '../facet'
4+
import { NO_VALUE } from '../types'
5+
import { Unwrap } from './Unwrap'
6+
7+
it('renders the child with unwrapped data', () => {
8+
const mockText = 'Foo'
9+
const mockFacet = createFacet({ initialValue: mockText })
10+
render(<Unwrap data={mockFacet}>{(data) => <>{data}</>}</Unwrap>)
11+
expect(screen.queryByText(mockText)).toBeInTheDocument()
12+
})
13+
14+
it('renders the child with unwrapped nullish data', () => {
15+
const mockText = 'Bar'
16+
const mockData = undefined
17+
const mockFacet = createFacet({ initialValue: mockData })
18+
render(<Unwrap data={mockFacet}>{(data) => <>{`${mockText}${data}`}</>}</Unwrap>)
19+
expect(screen.queryByText(`${mockText}${mockData}`)).toBeInTheDocument()
20+
})
21+
22+
it('does not render the child with NO_VALUE', () => {
23+
const mockText = 'Baz'
24+
const mockFacet = createFacet<boolean>({ initialValue: NO_VALUE })
25+
render(<Unwrap data={mockFacet}>{() => <>{mockText}</>}</Unwrap>)
26+
expect(screen.queryByText(mockText)).not.toBeInTheDocument()
27+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ReactElement } from 'react'
2+
import { useFacetUnwrap } from '../hooks'
3+
import { Facet, NO_VALUE, Value } from '../types'
4+
5+
/**
6+
* Renders a child with an unwrapped given facet value
7+
*
8+
* @param data facet value
9+
* @param children render prop which receives the unwrapped facet
10+
*/
11+
export const Unwrap = <T extends Value>({
12+
data,
13+
children,
14+
}: {
15+
data: Facet<T>
16+
children: (data: T) => ReactElement | null
17+
}) => {
18+
const unwrapped = useFacetUnwrap(data)
19+
return unwrapped === NO_VALUE ? null : children(unwrapped)
20+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export * from './Map'
22
export * from './Mount'
3+
export * from './Times'
4+
export * from './Unwrap'
35
export * from './With'

0 commit comments

Comments
 (0)