@@ -21,10 +21,10 @@ It's the API design that, using the classic HOC pattern, allows you to write Rea
21
21
Let's take a look at typical example of hooks usage:
22
22
23
23
``` tsx
24
- import { Input , Button , FormContainer , ErrorMessage } from " ui-lib "
25
- import { useUnit } from " effector-react "
24
+ import { useUnit } from ' effector-react ' ;
25
+ import { Button , ErrorMessage , FormContainer , Input } from ' ui-lib ' ;
26
26
27
- import * as model from " ./form-model"
27
+ import * as model from ' ./form-model' ;
28
28
29
29
export function UserForm() {
30
30
const {
@@ -42,16 +42,16 @@ export function UserForm() {
42
42
lastName: model .lastNameChanged ,
43
43
formSubmitted: model .formSubmitted ,
44
44
error: model .$error ,
45
- })
45
+ });
46
46
47
47
return (
48
48
<FormContainer >
49
49
<Input value = { name } onChange = { nameChanged } />
50
50
<Input value = { lastName } onChange = { lastNameChanged } />
51
- { error && ( <ErrorMessage text = { error } />) }
51
+ { error && <ErrorMessage text = { error } />}
52
52
<Button type = " submit" disabled = { ! formValid } onClick = { formSubmitted } />
53
53
</FormContainer >
54
- )
54
+ );
55
55
}
56
56
```
57
57
@@ -63,15 +63,12 @@ This can be fixed by moving the subscriptions further down the component tree by
63
63
64
64
``` tsx
65
65
function UserFormSubmitButton() {
66
- const {
67
- formValid,
68
- formSubmitted,
69
- } = useUnit ({
66
+ const { formValid, formSubmitted } = useUnit ({
70
67
formValid: model .$formValid ,
71
- formSubmitted: model .formSubmitted
72
- })
68
+ formSubmitted: model .formSubmitted ,
69
+ });
73
70
74
- return <Button type = " submit" disabled = { ! formValid } onClick = { formSubmitted } />
71
+ return <Button type = " submit" disabled = { ! formValid } onClick = { formSubmitted } />;
75
72
}
76
73
```
77
74
@@ -84,7 +81,7 @@ Also, in most cases it's not a big problem, since React is pretty fast at diffin
84
81
That's where reflect comes to the rescue:
85
82
86
83
``` tsx
87
- import { reflect , variant } from " @effector/reflect"
84
+ import { reflect , variant } from ' @effector/reflect' ;
88
85
89
86
export function UserForm() {
90
87
return (
@@ -94,43 +91,43 @@ export function UserForm() {
94
91
<Error />
95
92
<SubmitButton />
96
93
</FormContainer >
97
- )
94
+ );
98
95
}
99
96
100
97
const Name = reflect ({
101
98
view: Input ,
102
99
bind: {
103
100
value: model .$name ,
104
- onChange: model .nameChanged
105
- }
106
- })
101
+ onChange: model .nameChanged ,
102
+ },
103
+ });
107
104
108
105
const LastName = reflect ({
109
106
view: Input ,
110
107
bind: {
111
108
value: model .$lastName ,
112
- onChange: model .lastNameChanged
113
- }
114
- })
109
+ onChange: model .lastNameChanged ,
110
+ },
111
+ });
115
112
116
113
const Error = variant ({
117
114
if: model .$error ,
118
115
then: reflect ({
119
116
view: ErrorMessage ,
120
117
bind: {
121
118
text: model .$error ,
122
- }
123
- })
124
- })
119
+ },
120
+ }),
121
+ });
125
122
126
123
const SubmitButton = reflect ({
127
124
view: Button ,
128
125
bind: {
129
- type: " submit" , // plain values are allowed too!
130
- disabled: model .$formValid .map (valid => ! valid ),
131
- onClick: model .formSubmitted
132
- }
133
- })
126
+ type: ' submit' , // plain values are allowed too!
127
+ disabled: model .$formValid .map (( valid ) => ! valid ),
128
+ onClick: model .formSubmitted ,
129
+ },
130
+ });
134
131
```
135
132
136
133
Here we've separated this component into small parts, which were created in a convenient way using ` reflect ` operators, which is a very simple description of the ` props -> values ` mapping, which is easier to read and modify.
@@ -171,9 +168,9 @@ Static method to create a component bound to effector stores and events as store
171
168
172
169
``` tsx
173
170
// ./user.tsx
174
- import React , { FC , ChangeEvent } from ' react' ;
175
- import { createEvent , restore } from ' effector' ;
176
171
import { reflect } from ' @effector/reflect' ;
172
+ import { createEvent , restore } from ' effector' ;
173
+ import React , { ChangeEvent , FC } from ' react' ;
177
174
178
175
// Base components
179
176
type InputProps = {
@@ -202,7 +199,7 @@ const Name = reflect({
202
199
view: Input ,
203
200
bind: {
204
201
value: $name ,
205
- placeholder: " Name" ,
202
+ placeholder: ' Name' ,
206
203
onChange: changeName .prepend (inputChanged ),
207
204
},
208
205
});
@@ -211,7 +208,7 @@ const Age = reflect({
211
208
view: Input ,
212
209
bind: {
213
210
value: $age ,
214
- placeholder: " Age" ,
211
+ placeholder: ' Age' ,
215
212
onChange: changeAge .prepend (parseInt ).prepend (inputChanged ),
216
213
},
217
214
});
@@ -253,10 +250,10 @@ Method allows to change component based on value in `$typeSelector`. Optional `b
253
250
When ` Field ` is rendered it checks for ` $fieldType ` value, selects the appropriate component from ` cases ` and bound props to it.
254
251
255
252
``` tsx
256
- import React from ' react' ;
257
- import { createStore , createEvent } from ' effector' ;
258
253
import { variant } from ' @effector/reflect' ;
259
- import { TextInput , Range , DateSelector } from ' @org/ui-lib' ;
254
+ import { DateSelector , Range , TextInput } from ' @org/ui-lib' ;
255
+ import { createEvent , createStore } from ' effector' ;
256
+ import React from ' react' ;
260
257
261
258
const $fieldType = createStore <' date' | ' number' | ' string' >(' string' );
262
259
@@ -315,7 +312,7 @@ const Items: React.FC = list({
315
312
mapItem: {
316
313
propName : (item : Item , index : number ) => propValue , // maps array store item to View props
317
314
},
318
- getKey : (item : Item ) => React .Key // optional, will use index by default
315
+ getKey : (item : Item ) => React .Key , // optional, will use index by default
319
316
});
320
317
```
321
318
@@ -337,9 +334,9 @@ Method creates component, which renders list of `view` components based on items
337
334
#### Example
338
335
339
336
``` tsx
340
- import React from ' react' ;
341
- import { createStore , createEvent } from ' effector' ;
342
337
import { list } from ' @effector/reflect' ;
338
+ import { createEvent , createStore } from ' effector' ;
339
+ import React from ' react' ;
343
340
344
341
const $color = createStore (' red' );
345
342
@@ -382,8 +379,8 @@ Method for creating reflect a view. So you can create a UI kit by views and use
382
379
383
380
``` tsx
384
381
// ./ui.tsx
385
- import React , { FC , useCallback , ChangeEvent , MouseEvent } from ' react' ;
386
382
import { createReflect } from ' @effector/reflect' ;
383
+ import React , { ChangeEvent , FC , MouseEvent , useCallback } from ' react' ;
387
384
388
385
// Input
389
386
type InputProps = {
@@ -416,10 +413,10 @@ export const reflectButton = createReflect(Button);
416
413
417
414
``` tsx
418
415
// ./user.tsx
419
- import React , { FC } from ' react' ;
420
416
import { createEvent , restore } from ' effector' ;
417
+ import React , { FC } from ' react' ;
421
418
422
- import { reflectInput , reflectButton } from ' ./ui' ;
419
+ import { reflectButton , reflectInput } from ' ./ui' ;
423
420
424
421
// Model
425
422
const changeName = createEvent <string >();
@@ -464,9 +461,9 @@ Hooks is an object passed to `variant()` or `match()` with properties `mounted`
464
461
#### Example
465
462
466
463
``` tsx
467
- import { createStore , createEvent } from ' effector' ;
468
464
import { reflect , variant } from ' @effector/reflect' ;
469
- import { TextInput , Range } from ' @org/my-ui' ;
465
+ import { Range , TextInput } from ' @org/my-ui' ;
466
+ import { createEvent , createStore } from ' effector' ;
470
467
471
468
const $type = createStore <' text' | ' range' >(' text' );
472
469
const $value = createStore (' ' );
@@ -493,10 +490,8 @@ const Field = variant({
493
490
494
491
When ` Field ` is mounted, ` fieldMounted ` and ` rangeMounted ` would be called.
495
492
496
-
497
493
### SSR and tests via Fork API
498
494
499
-
500
495
Since [ effector-react 22.5.0] ( https://github.com/effector/effector/releases/tag/effector-react%4022.5.0 ) it is no longer necessary to use ` @effector/reflect/ssr ` due to isomorphic nature of ` effector-react ` hooks after this release, you can just use ` @effector/reflect ` main imports.
501
496
502
497
Just add ` Provider ` from ` effector-react ` to your app root, and you are good to go.
@@ -507,7 +502,7 @@ Also for this case you need to use `event.prepend(params => params.something)` i
507
502
508
503
``` tsx
509
504
// ./ui.tsx
510
- import React , { FC , useCallback , ChangeEvent , MouseEvent } from ' react' ;
505
+ import React , { ChangeEvent , FC , MouseEvent , useCallback } from ' react' ;
511
506
512
507
// Input
513
508
type InputProps = {
@@ -522,24 +517,24 @@ const Input: FC<InputProps> = ({ value, onChange }) => {
522
517
523
518
``` tsx
524
519
// ./app.tsx
525
- import React , { FC } from ' react' ;
526
- import { createEvent , restore , sample , Scope } from ' effector' ;
527
520
import { reflect } from ' @effector/reflect' ;
521
+ import { createEvent , restore , sample , Scope } from ' effector' ;
528
522
import { Provider } from ' effector-react' ;
523
+ import React , { FC } from ' react' ;
529
524
530
525
import { Input } from ' ./ui' ;
531
526
532
527
// Model
533
- export const appStarted = createEvent <{name: string }>()
528
+ export const appStarted = createEvent <{ name: string }>();
534
529
535
530
const changeName = createEvent <string >();
536
531
const $name = restore (changeName , ' ' );
537
532
538
533
sample ({
539
534
clock: appStarted ,
540
- fn : ctx => ctx .name ,
535
+ fn : ( ctx ) => ctx .name ,
541
536
target: changeName ,
542
- })
537
+ });
543
538
544
539
// Component
545
540
const Name = reflect ({
@@ -561,7 +556,7 @@ export const App: FC<{ scope: Scope }> = ({ scope }) => {
561
556
562
557
``` tsx
563
558
// ./server.tsx
564
- import { fork , serialize , allSettled } from ' effector' ;
559
+ import { allSettled , fork , serialize } from ' effector' ;
565
560
566
561
import { App , appStarted } from ' ./app' ;
567
562
@@ -572,7 +567,7 @@ const render = async (reqCtx) => {
572
567
scope: serverScope ,
573
568
params: {
574
569
name: reqCtx .cookies .name ,
575
- }
570
+ },
576
571
});
577
572
578
573
const content = renderToString (<App scope = { serverScope } />);
@@ -592,15 +587,15 @@ const render = async (reqCtx) => {
592
587
``` tsx
593
588
// client.tsx
594
589
import { fork } from ' effector' ;
595
- import { hydrateRoot } from ' react-dom/client'
590
+ import { hydrateRoot } from ' react-dom/client' ;
596
591
597
592
import { App , appStarted } from ' ./app' ;
598
593
599
594
const clientScope = fork ({
600
- values: window .__initialState__
601
- })
595
+ values: window .__initialState__ ,
596
+ });
602
597
603
- hydrateRoot (document .body , <App scope = { clientScope } />)
598
+ hydrateRoot (document .body , <App scope = { clientScope } />);
604
599
```
605
600
606
601
## Release process
0 commit comments