File tree Expand file tree Collapse file tree 4 files changed +63
-5
lines changed Expand file tree Collapse file tree 4 files changed +63
-5
lines changed Original file line number Diff line number Diff line change @@ -31,15 +31,17 @@ export function reflectFactory(context: Context) {
31
31
return function reflect <
32
32
Props ,
33
33
Bind extends BindableProps < Props > = BindableProps < Props > ,
34
- > ( config : ReflectConfig < Props , Bind > ) : React . FC < PartialBoundProps < Props , Bind > > {
34
+ > (
35
+ config : ReflectConfig < Props , Bind > ,
36
+ ) : React . ExoticComponent < PartialBoundProps < Props , Bind > > {
35
37
const { stores, events, data } = sortProps ( config ) ;
36
38
37
- return ( props ) => {
39
+ return React . forwardRef ( ( props , ref ) => {
38
40
const storeProps = context . useUnit ( stores ) ;
39
41
const eventsProps = context . useUnit ( events ) ;
40
42
41
43
const elementProps : Props = Object . assign (
42
- { } ,
44
+ { ref } ,
43
45
storeProps ,
44
46
eventsProps ,
45
47
data ,
@@ -58,7 +60,7 @@ export function reflectFactory(context: Context) {
58
60
} , [ ] ) ;
59
61
60
62
return React . createElement ( config . view as any , elementProps as any ) ;
61
- } ;
63
+ } ) ;
62
64
} ;
63
65
}
64
66
Original file line number Diff line number Diff line change @@ -7,10 +7,14 @@ export interface Context {
7
7
useList : typeof useList ;
8
8
}
9
9
10
+ type UnbindableProps = 'key' | 'ref' ;
11
+
10
12
type Storify < Prop > = Omit < Store < Prop > , 'updates' | 'reset' | 'on' | 'off' | 'thru' > ;
11
13
12
14
export type BindableProps < Props > = {
13
- [ Key in keyof Props ] ?: Props [ Key ] extends ( _payload : any ) => void
15
+ [ Key in Exclude < keyof Props , UnbindableProps > ] ?: Props [ Key ] extends (
16
+ payload : any ,
17
+ ) => void
14
18
? Storify < Props [ Key ] > | Props [ Key ] | Event < void >
15
19
: Storify < Props [ Key ] > | Props [ Key ] ;
16
20
} ;
Original file line number Diff line number Diff line change @@ -145,6 +145,20 @@ test('component inside', async () => {
145
145
expect ( inputName . value ) . toBe ( 'Bob' ) ;
146
146
} ) ;
147
147
148
+ test ( 'forwardRef' , async ( ) => {
149
+ const Name = reflect ( {
150
+ view : React . forwardRef ( ( props , ref : React . ForwardedRef < HTMLInputElement > ) => {
151
+ return < input data-testid = "name" ref = { ref } /> ;
152
+ } ) ,
153
+ bind : { } ,
154
+ } ) ;
155
+
156
+ const ref = React . createRef < HTMLInputElement > ( ) ;
157
+
158
+ const container = render ( < Name ref = { ref } /> ) ;
159
+ expect ( container . getByTestId ( 'name' ) ) . toBe ( ref . current ) ;
160
+ } ) ;
161
+
148
162
describe ( 'hooks' , ( ) => {
149
163
describe ( 'mounted' , ( ) => {
150
164
test ( 'callback' , ( ) => {
Original file line number Diff line number Diff line change @@ -122,3 +122,41 @@ import { reflect } from '../src';
122
122
123
123
expectType < React . FC > ( ReflectedButton ) ;
124
124
}
125
+
126
+ // reflect should not allow binding ref
127
+ {
128
+ const Text = React . forwardRef (
129
+ ( _ : { value : string } , ref : React . ForwardedRef < HTMLSpanElement > ) => null ,
130
+ ) ;
131
+
132
+ const ReflectedText = reflect ( {
133
+ view : Text ,
134
+ bind : {
135
+ // @ts -expect-error
136
+ ref : React . createRef < HTMLSpanElement > ( ) ,
137
+ } ,
138
+ } ) ;
139
+
140
+ expectType < React . VFC > ( ReflectedText ) ;
141
+ }
142
+
143
+ // reflect should pass ref through
144
+ {
145
+ const $value = createStore < string > ( '' ) ;
146
+ const Text = React . forwardRef (
147
+ ( _ : { value : string } , ref : React . ForwardedRef < HTMLSpanElement > ) => null ,
148
+ ) ;
149
+
150
+ const ReflectedText = reflect ( {
151
+ view : Text ,
152
+ bind : { value : $value } ,
153
+ } ) ;
154
+
155
+ const App : React . FC = ( ) => {
156
+ const ref = React . useRef ( null ) ;
157
+
158
+ return < ReflectedText ref = { ref } /> ;
159
+ } ;
160
+
161
+ expectType < React . FC > ( App ) ;
162
+ }
You can’t perform that action at this time.
0 commit comments