Skip to content

Commit ac09efe

Browse files
committed
feat: add inline composition
1 parent 5d4db78 commit ac09efe

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- [Custom render and retrieving props from composed](#custom-render-and-retrieving-props-from-composed)
1717
- [Leading with multiple params](#leading-with-multiple-params)
1818
- [Typescript support](#typescript-support)
19+
- [Inline composition](#inline-composition)
1920

2021
## 🧐   Why
2122

@@ -194,6 +195,25 @@ const Composed = adopt<RenderProps, Props>({
194195
</Composed>
195196
```
196197

198+
### Inline composition
199+
200+
If you dont care about [typings](#typescript-support) and need something more easy and quick, you can choose to use a inline composition by importing `<Adopt>` component and passing your mapper as prop:
201+
202+
```js
203+
import React from 'react'
204+
import { Adopt } from 'react-adopt'
205+
import { Value } from 'react-powerplug'
206+
207+
const mapper = {
208+
greet: <Value initial="Hi" />,
209+
name: <Value initial="John" />
210+
}
211+
212+
<Adopt mapper={mapper}>
213+
{({ greet, name }) => /* ... */}
214+
</Adopt>
215+
```
216+
197217
## 🕺 &nbsp; Contribute
198218

199219
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device

src/index.test.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as React from 'react'
22
import { shallow, mount } from 'enzyme'
33
import { Value } from 'react-powerplug'
44

5-
import { adopt } from './'
5+
import { adopt, Adopt } from './'
66

77
test('return one component with children props as function', () => {
88
interface RenderProps {
@@ -130,3 +130,39 @@ test('throw with a wrong value on mapper', () => {
130130
'The render props object mapper just accept valid elements as value'
131131
)
132132
})
133+
134+
test('inline composition using <Adopt> component', () => {
135+
const Foo = ({ children }) => children('foo')
136+
const children = jest.fn(({ foo }) => <div>{foo}</div>)
137+
138+
const mapper = {
139+
foo: <Foo />,
140+
}
141+
142+
const element = <Adopt mapper={mapper}>{children}</Adopt>
143+
144+
mount(element)
145+
expect(children).toHaveBeenCalledWith({ foo: 'foo' })
146+
147+
const result = shallow(element)
148+
149+
expect(result.children().length).toBe(1)
150+
expect(result.html()).toBe('<div>foo</div>')
151+
})
152+
153+
test('changing <Adopt> properties on the fly', () => {
154+
const Foo = ({ children, value }) => children(value)
155+
const children = jest.fn(({ foo }) => <div>{foo}</div>)
156+
157+
const Component = ({ value }) => (
158+
<Adopt mapper={{ foo: <Foo value={value} /> }}>
159+
{({ foo }) => <div>{foo}</div>}
160+
</Adopt>
161+
)
162+
163+
const wrapper = mount(<Component value="foo" />)
164+
165+
expect(wrapper.text()).toBe('foo')
166+
wrapper.setProps({ value: 'bar' })
167+
expect(wrapper.text()).toBe('bar')
168+
})

src/index.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,15 @@ export function adopt<RP = any, P = any>(mapper: Mapper<RP, P>): RPC<RP, P> {
8181

8282
return keys(mapper).reduce(reducer, Children)
8383
}
84+
85+
export type AdoptProps<RP, P> = P & {
86+
mapper: Mapper<RP, P>
87+
children: ChildrenFn<RP>
88+
}
89+
90+
export const Adopt: React.SFC<AdoptProps<any, any>> = props => {
91+
const Composed = adopt(props.mapper)
92+
const composedProps = omit(['children', 'mapper'], props)
93+
94+
return <Composed {...composedProps}>{props.children}</Composed>
95+
}

0 commit comments

Comments
 (0)