-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1327 lines (977 loc) · 166 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html><html class="no-js" lang="en"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><title>React Starter Kit - www.reactstarterkit.com</title><meta name="description" content=""/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/assets/vendors.a64ddcfe.chunk.js" as="script"/><link rel="preload" href="/assets/client.7f687ee0.js" as="script"/><link rel="preload" href="/assets/vendors~about~admin~contact~home~login~not-found~privacy~register.65ec8708.chunk.js" as="script"/><link rel="preload" href="/assets/about~admin~contact~home~login~not-found~privacy~register.1bfade13.chunk.js" as="script"/><link rel="preload" href="/assets/home.582c44e2.chunk.js" as="script"/><link rel="manifest" href="/site.webmanifest"/><link rel="stylesheet" type="text/css" href="/theme.css"/><link rel="apple-touch-icon" href="/icon.png"/><style id="css">html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:rgba(0,0,0,0)}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}:root{--font-family-base:"Segoe UI","HelveticaNeue-Light",sans-serif;--max-content-width:1000px;--screen-xs-min:480px;--screen-sm-min:768px;--screen-md-min:992px;--screen-lg-min:1200px}html{color:#222;font-weight:100;font-size:1em;font-family:Segoe UI,HelveticaNeue-Light,sans-serif;font-family:var(--font-family-base);line-height:1.375}body{margin:0}a{color:#0074c2}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}audio,canvas,iframe,img,svg,video{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}.browserupgrade{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}@media print{*,:after,:before{background:rgba(0,0,0,0)!important;color:#000!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" ("attr(href) ")"}abbr[title]:after{content:" ("attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}}:root{--font-family-base:"Segoe UI","HelveticaNeue-Light",sans-serif;--max-content-width:1000px;--screen-xs-min:480px;--screen-sm-min:768px;--screen-md-min:992px;--screen-lg-min:1200px;--brand-color:#61dafb}.O9oW9{background:#373277;color:#fff}.qQ2mF{margin:0 auto;padding:20px 0;max-width:1000px;max-width:var(--max-content-width)}._2oS_y{color:color(#61dafb lightness(10%));color:color(var(--brand-color) lightness(10%));text-decoration:none;font-size:1.75em}._230aH{margin-left:10px}._2AXOj{text-align:center}._3dmwX{margin:0;padding:10px;font-weight:400;font-size:4em;line-height:1em}.I2eY9{padding:0;color:hsla(0,0%,100%,.5);font-size:1.25em;margin:0}._2gcJx{float:right;margin:6px 0 0}.Ntl35{display:inline-block;padding:3px 8px;text-decoration:none;font-size:1.125em}.Ntl35,.Ntl35:active,.Ntl35:visited{color:hsla(0,0%,100%,.6)}.Ntl35:hover{color:#fff}._2UNlq{margin-right:8px;margin-left:8px;border-radius:3px;background:rgba(0,0,0,.15);color:#fff}._2UNlq:hover{background:rgba(0,0,0,.3)}._3vZVG{color:hsla(0,0%,100%,.3)}:root{--font-family-base:"Segoe UI","HelveticaNeue-Light",sans-serif;--max-content-width:1000px;--screen-xs-min:480px;--screen-sm-min:768px;--screen-md-min:992px;--screen-lg-min:1200px}._1avl7{padding-left:20px;padding-right:20px}._3YPN-{margin:0 auto;padding:0 0 40px;max-width:1000px;max-width:var(--max-content-width)}.-EKGZ{margin:0 0 2rem}._3GwAp{font-size:24px;font-size:1.5rem}._107uo h1,._107uo h2,._107uo h3,._107uo h4,._107uo h5,._107uo h6{font-size:18px;font-size:1.125rem}._107uo pre{white-space:pre-wrap;font-size:14px;font-size:.875rem}._107uo img{max-width:100%}:root{--font-family-base:"Segoe UI","HelveticaNeue-Light",sans-serif;--max-content-width:1000px;--screen-xs-min:480px;--screen-sm-min:768px;--screen-md-min:992px;--screen-lg-min:1200px}._1QFug{background:#f5f5f5;color:#333}._1aTkE{margin:0 auto;padding:20px 8px;max-width:1000px;max-width:var(--max-content-width);text-align:center;font-size:1.5em}._2iH7A,._2iH7A:active,._2iH7A:hover,._2iH7A:visited{color:#333;text-decoration:none}._2iH7A:hover{text-decoration:underline}._3GZrp{padding-right:15px;padding-left:15px}:root{--font-family-base:"Segoe UI","HelveticaNeue-Light",sans-serif;--max-content-width:1000px;--screen-xs-min:480px;--screen-sm-min:768px;--screen-md-min:992px;--screen-lg-min:1200px}._1UUMy{background:#333;color:#fff}._3dfAC{margin:0 auto;padding:20px 15px;max-width:1000px;max-width:var(--max-content-width);text-align:center}._3ReUN{color:hsla(0,0%,100%,.5)}._297xE{color:hsla(0,0%,100%,.3)}._3qHjF,._3ReUN{padding:2px 5px;font-size:1em}._3qHjF,._3qHjF:active,._3qHjF:visited{color:hsla(0,0%,100%,.6);text-decoration:none}._3qHjF:hover{color:#fff}</style></head><body><div id="app"><div><div class="O9oW9"><div class="qQ2mF"><div class="_2gcJx" role="navigation"><a href="/about" class="Ntl35">About</a><a href="/contact" class="Ntl35">Contact</a><span class="_3vZVG"> | </span><a href="/login" class="Ntl35">Log in</a><span class="_3vZVG">or</span><a href="/register" class="Ntl35 _2UNlq">Sign up</a></div><a href="/" class="_2oS_y"><img src="/assets/2f751285.png" srcSet="/assets/8844262b.png 2x" width="38" height="38" alt="React"/><span class="_230aH">Your Company</span></a><div>aaaaaaaaaaaaaaaaaa</div><div><button type="button" class="ant-btn ant-btn-primary"><span>Primary</span></button><button type="button" class="ant-btn"><span>Default</span></button><button type="button" class="ant-btn ant-btn-dashed"><span>Dashed</span></button><button type="button" class="ant-btn ant-btn-danger"><span>Danger</span></button><button type="button" class="ant-btn ant-btn-link"><span>Link</span></button></div><div class="_2AXOj"><h1 class="_3dmwX">React</h1><p class="I2eY9">Complex web apps made easy</p></div></div></div><div class="_1avl7"><div class="_3YPN-"><h1>React.js News</h1><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/proxies-with-redux-types">Using Proxies with Redux Types</a></h1><div class="_107uo">
<p>One of the most common problems that I run into when using Redux is trying to figure out why an action is not being captured by a reducer. For someone just getting starting with Redux, debugging this issue can be especially overwhelming because of how Redux manages data flow. So before you start pouring over configuration code, or the logic contained in your action creators and reducers, please, make sure your action types are defined and spelled correctly.</p>
<!--more-->
<p>One of the most common problems that I run into when using Redux is trying to figure out why an action is not being captured by a reducer. For someone just getting starting with Redux, debugging this issue can be especially overwhelming because of how Redux manages data flow. So before you start pouring over configuration code, or the logic contained in your action creators and reducers, please, make sure your action types are defined and spelled correctly.</p>
<p>In any application that I have built, most bugs that I have run into are simply due to typos. However, the solution to this particular problem is harder to spot because no errors are raised when the application is run. Take a look at the snippet below.</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="c1">// actionTypes.js</span>
<span class="kr">export</span> <span class="kr">const</span> <span class="nx">FETCH_FILE_REQUEST</span> <span class="o">=</span> <span class="s1">'fetch_file_request'</span><span class="p">;</span>
<span class="kr">export</span> <span class="kr">const</span> <span class="nx">FETCH_FILE_SUCCESS</span> <span class="o">=</span> <span class="s1">'fetch_file_success'</span><span class="p">;</span>
<span class="kr">export</span> <span class="kr">const</span> <span class="nx">FETCH_FILE_FAIL</span> <span class="o">=</span> <span class="s1">'fetch_file_fail'</span><span class="p">;</span>
<span class="c1">// filesReducer.js</span>
<span class="kr">import</span> <span class="p">{</span>
<span class="nx">FETCH_FILE_REQUEST</span><span class="p">,</span>
<span class="nx">FETCH_FILE_SUCESS</span><span class="p">,</span>
<span class="nx">FETCH_FILE_FAIL</span>
<span class="p">}</span> <span class="nx">from</span> <span class="s1">'../actions/actionTypes'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">filesReducer</span> <span class="o">=</span> <span class="p">(</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{},</span> <span class="nx">action</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="na">FETCH_FILE_SUCESS</span><span class="p">:</span>
<span class="k">return</span> <span class="p">{</span> <span class="p">...</span><span class="nx">state</span><span class="p">,</span> <span class="na">file</span><span class="p">:</span> <span class="nx">action</span><span class="p">.</span><span class="nx">payload</span> <span class="p">};</span>
<span class="nl">default</span><span class="p">:</span>
<span class="k">return</span> <span class="nx">state</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kr">export</span> <span class="k">default</span> <span class="nx">filesReducer</span><span class="p">;</span>
</code></pre>
</div>
<p>Assuming we dispatched an action with type FETCH_FILE_SUCCESS, the filesReducer should catch the action before the default case is returned. But what if that is not happening? Where do we start the debugging process. There does not appear to be anything wrong with the code in the reducer; the action type was imported and matches the case in the switch statement. There are no errors in the browser. Where is the issue?</p>
<p>You may have noticed that I misspelled SUCCESS in filesReducer.js, but the reason this can be hard to catch is because importing undefined types does not cause an error, so when we import FETCH_FILE_SUCESS, its value is actually undefined, so our reducer always hits the default case.</p>
<p>It would be nice if the existing import/export system could help us catch this. Unfortunately, since action types are just strings, validating their existence is challenging. Luckily, we have another option.</p>
<h4>Enter Proxies</h4>
<p>Proxies are a feature of ES2015 that allow us to customize operations on a object. They can be used in many different ways, and you can find some useful examples <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">here</a> and <a href="https://developers.google.com/web/updates/2016/02/es2015-proxies">here</a>. For our problem, this example from <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">Mozilla</a> looks promising:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="kd">let</span> <span class="nx">validator</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">set</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">prop</span> <span class="o">===</span> <span class="s1">'age'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">Number</span><span class="p">.</span><span class="nx">isInteger</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">TypeError</span><span class="p">(</span><span class="s1">'The age is not an integer'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">value</span> <span class="o">></span> <span class="mi">200</span><span class="p">)</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">RangeError</span><span class="p">(</span><span class="s1">'The age seems invalid'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// The default behavior to store the value</span>
<span class="nx">obj</span><span class="p">[</span><span class="nx">prop</span><span class="p">]</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="c1">// Indicate success</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="kd">let</span> <span class="nx">person</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Proxy</span><span class="p">({},</span> <span class="nx">validator</span><span class="p">);</span>
<span class="nx">person</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">person</span><span class="p">.</span><span class="nx">age</span><span class="p">);</span> <span class="c1">// 100</span>
<span class="nx">person</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="s1">'young'</span><span class="p">;</span> <span class="c1">// Throws an exception</span>
<span class="nx">person</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">300</span><span class="p">;</span> <span class="c1">// Throws an exception</span>
</code></pre>
</div>
<p>So if proxies can be used to validate that properties assigned to an object are of a certain type and value, we should definitely be able to ensure that our action types are never undefined, or else throw an error that will be easy for us to fix. Let’s refactor our actionTypes.js file.</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="c1">// actionTypes.js</span>
<span class="kr">const</span> <span class="nx">types</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">FETCH_FILE_REQUEST</span><span class="p">:</span> <span class="s1">'fetch_file_request'</span><span class="p">,</span>
<span class="na">FETCH_FILE_SUCCESS</span><span class="p">:</span> <span class="s1">'fetch_file_success'</span><span class="p">,</span>
<span class="na">FETCH_FILE_FAIL</span><span class="p">:</span> <span class="s1">'fetch_file_fail'</span>
<span class="p">}</span>
<span class="kr">const</span> <span class="nx">typeValidator</span> <span class="o">=</span> <span class="p">{</span>
<span class="nx">get</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">prop</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">obj</span><span class="p">[</span><span class="nx">prop</span><span class="p">])</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">prop</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nx">TypeError</span><span class="p">(</span><span class="err">`</span><span class="nx">$</span><span class="p">{</span><span class="nx">prop</span><span class="p">}</span> <span class="nx">is</span> <span class="nx">not</span> <span class="nx">a</span> <span class="nx">valid</span> <span class="nx">action</span> <span class="nx">type</span><span class="err">`</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Proxy</span><span class="p">(</span><span class="nx">types</span><span class="p">,</span> <span class="nx">typeValidator</span><span class="p">);</span>
</code></pre>
</div>
<p>First, we define a object containing all our action types. Then we define our validator handler typeValidator. The get method inside our handler is called a trap, and provides access to the properties of a object. If the property we are looking for, an action type, in this case, exists in the types object, return that prop, unmodified. Otherwise, throw an error because the prop does not exist.</p>
<p>Finally, export a new proxy, passing the types object as the target and the typeValidator as the handler. However, it is important to note that the ES2015 module system does not work well with proxies, so module.exports and require() must be used for exporting and importing the types.</p>
<p>Barely any code needs to change in the reducer and action creator files, but in order for the action types to be imported successfully, we just need couple lines of code in a new file:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="c1">// actionTypesProxy.js</span>
<span class="kr">export</span> <span class="kr">const</span> <span class="p">{</span>
<span class="nx">FETCH_FILE_REQUEST</span><span class="p">,</span>
<span class="nx">FETCH_FILE_SUCCESS</span><span class="p">,</span>
<span class="nx">FETCH_FILE_FAIL</span><span class="p">,</span>
<span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'./actionTypes'</span><span class="p">);</span>
<span class="c1">// in the reducer and action creator files</span>
<span class="c1">// change '../actions/actionTypes' to</span>
<span class="c1">// '../actions/actionTypesProxy'</span>
</code></pre>
</div>
<p>By creating a proxy to verify the existence of an action type, we no longer have to worry about correctly naming a property upon import because an error will be thrown in the browser console as soon as the application starts. So, reduce the number headaches you get when developing an application using Redux and start using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy">proxies</a>.</p>
<p>Interested in learning how to build applications using Redux with ReactJS. Check out this online course! <a href="https://www.udemy.com/react-redux/">Modern React with Redux</a></p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/component-kits-for-react-native">Component Kits for React Native</a></h1><div class="_107uo">
<p>You won’t find as many styling solutions for React Native as you will for React JS. This stems from two simple realities:</p>
<ol>
<li>React Native is a much smaller target for component libraries than traditional CSS frameworks. In other words, Bootstrap CSS can be used with any web framework, whereas component libraries for React Native only work with…you guessed it…React Native.</li>
<li>Customizing React Native styling isn’t the easiest thing in the world. Many apps demand custom styling, which makes component kits not too useful. In addition, it is challenging to customize each and every component, as the flexibility that you gain with traditional CSS on the web doesn’t carry over easily to component libraries.</li>
</ol>
<p>With that said, here are a few options.</p>
<!--more-->
<p>You won’t find as many styling solutions for React Native as you will for React JS. This stems from two simple realities:</p>
<ol>
<li>React Native is a much smaller target for component libraries than traditional CSS frameworks. In other words, Bootstrap CSS can be used with any web framework, whereas component libraries for React Native only work with…you guessed it…React Native.</li>
<li>Customizing React Native styling isn’t the easiest thing in the world. Many apps demand custom styling, which makes component kits not too useful. In addition, it is challenging to customize each and every component, as the flexibility that you gain with traditional CSS on the web doesn’t carry over easily to component libraries.</li>
</ol>
<p>With that said, here are a few options.</p>
<h3>NativeBase - <a href="http://nativebase.io/">Essential cross-platform UI components for React Native</a>
</h3>
<p>A huge collection of components, most of which look quite nice. That’s the plus side. The down side is that some of the components are somewhat buggy. No offense to the library authors, its just the state of the library - it needs a bit of work. For example, here’s an issue I opened a few days ago when I discovered the swipe deck component crashed when only a single data element was provided: <a href="https://github.com/GeekyAnts/NativeBase/issues/562">DeskSwiper throws on single element lists · Issue #562 · GeekyAnts/NativeBase</a>. The authors fixed it up awfully fast, but, hey, that’s a bug that seems like it could have been caught earlier.</p>
<hr>
<h3>React Native Elements - <a href="https://github.com/react-native-community/react-native-elements">react-native-community/react-native-elements</a>
</h3>
<p>This is my personal favorite. The styling is generally platform agnostic; it won’t look out of place using it on either Android or iOS. Each component has simple customization, the docs are solid, and it comes with a good set of icons. This is a no-brainer.</p>
<hr>
<h3>React Native Material Design - <a href="https://github.com/react-native-material-design/react-native-material-design">react-native-material-design/react-native-material-design</a>
</h3>
<p>Another solid choice, but mostly only useful for Android. Again, its a bit unsettling to see material design - traditionally a stable of Android devices - on iOS. Besides that, the docs are still a work in progress, as evidenced by the lack of docs for nearly half of the components. Nonetheless, if you’re looking for a material design solution, this is better than nothing. It is also worth noting that the project looks generally unmaintained.</p>
<hr>
<h3>React Native Material Kit - <a href="https://github.com/xinthink/react-native-material-kit">xinthink/react-native-material-kit</a>
</h3>
<p>Another material design solution, but much better maintained than React Native Material Design. This one has the added benefit of a nicer customization API for creating your own custom components - see the docs on this. It also has some more dynamic components like progress bars and sliders, which you may not see on other frameworks. Anything that helps save you time to build your app is always a solid benefit.</p>
<hr>
<h3>Do Your Own Styling!</h3>
<p>If none of these choices float your boat, you can always learn how to style components from scratch yourself. I have a course on Udemy that will teach you how to make perfectly reusable components for your own projects. Check it out here: <a href="https://www.udemy.com/the-complete-react-native-and-redux-course/?couponCode=4IJ2N25F">The Complete React Native and Redux Course - Udemy</a></p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/the-diverse-react-navigation-ecosystem">The Diverse React Navigation Ecosystem</a></h1><div class="_107uo">
<p>The routing ecosystem around React and React Native is quite different. One is characterized by a strong incumbent, and the other is plagued by rapid change.</p>
<!--more-->
<h3>React JS</h3>
<p>No question about it, React Router (<a href="https://github.com/ReactTraining/react-router">ReactTraining/react-router</a>) is king here. They have the benefit of several years of active development, along with an active community submitting PR’s, fixes, etc. Supplement that with myriad tutorials and how-to’s and you end up with a well-supported, stable product. To be fair, React Router has suffered some major API upsets, and is nearly the poster-child for javascript fatigue but the maintainers have declared their lasting support for a few specific versions, which means you can plop down with V3 and be good to go for the next 12 to 24 months.</p>
<h3>React Native</h3>
<p>Ok, this is where things start to get really, really crazy. The most important thing to keep in mind is that the React Native team has produced three navigation helpers: NavigatorIOS, Navigator, and NavigatorExperimental.</p>
<ul>
<li>NavigatorIOS was quickly deprecated, as it was supported only by (you guessed it) IOS.</li>
<li>Navigator is the currently endorsed solution for navigation, at least if you are following the official docs. However, its about to be upset by-</li>
<li>NavigationExperimental. This is an updated navigator that has learned some lessons from Navigator, and has some solid integration with Redux. ‘Navigator’ is (or was!) sleighted to be deprecated in favor of NavigationExperimental at some point.</li>
</ul>
<p>Already you have three ‘official’ navigators supported by the React Native team. The big issue with all three of these is that they are somewhat lightweight and don’t include a lot of common navigation situations out of the box, like sidebars, tab bars, headers, etc. To solve that, the community has introduced…</p>
<ul>
<li>React Native Router Flux (<a href="https://github.com/aksonov/react-native-router-flux">aksonov/react-native-router-flux</a>). My personal favorite, this is router is based upon NavigationExperimental. You can imagine that the authors looked at NavigationExperimental, realized that everyone would be writing the same wrapper code around it, and so created this project.</li>
<li>React Native Router (t4t5/react-native-router). Haven’t used it, but it is colossally popular.</li>
<li>React Router Native (<a href="https://github.com/jmurzy/react-router-native">jmurzy/react-router-native</a>). Strives for API conformity with React Router (the above mentioned one). The great approach here is that they bring in the concept of a URL in native apps, where one doesn’t otherwise exist. This is a great approach that simplifies a lot of common routing situations.
Of course, there’s one more big solution that is supposedly going to become the standard:</li>
<li>React Navigation (<a href="https://github.com/react-community/react-navigation">react-community/react-navigation</a>). Seen as a solution that will soon be ‘official’ in the community, it is intended to replaced NavigationExperimental. This package is still in active development, so I expect at least a bit of API upset over the coming months. If you want to use official solutions, go with this, if you want a tried and true solution, go with React Native Router Flux.</li>
</ul>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/react-js-with-cloudinary">Leveraging React for Easy Image Management</a></h1><div class="_107uo">
<p><a href="https://facebook.github.io/react/">React</a> is a good tool when it comes to building flexible and reusable UI components. However, it’s “one of those libraries” that cannot handle all the tasks involved in building a full fleshed UI project. Other supporting tools - such as a recently announced <a href="https://github.com/cloudinary/cloudinary-react">React SDK</a> from <a href="http://cloudinary.com/?utm_source=Scotch&utm_medium=Sponsored_Post_6&utm_content=React_Gallery">Cloudinary</a> - are available to provide solutions that the React core cannot.</p>
<!--more-->
<p>In such cases where media (images and videos) becomes a heavy task to handle, <a href="http://cloudinary.com/?utm_source=Scotch&utm_medium=Sponsored_Post_6&utm_content=React_Gallery">Cloudinary</a> simplifies the process with the new React SDK. Let’s build and image library with Cloudinary and React using the <a href="https://github.com/cloudinary/cloudinary-react">Cloudinary’s React SDK</a>.</p>
<h2>Prerequisites</h2>
<p>The only requirements for using <a href="http://cloudinary.com/?utm_source=Scotch&utm_medium=Sponsored_Post_6&utm_content=React_Gallery">Cloudinary</a> in your existing React project are to install the React SDK and the upload widget. If you do not have an existing React project and want to try these examples, take the following steps:</p>
<h3>1. Install Dependencies</h3>
<p>We need a minimal amount of dependencies so we can focus on building a media library and not structuring a React app:</p>
<div class="language-json highlighter-rouge">
<pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"img-library"</span><span class="p">,</span><span class="w">
</span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.0"</span><span class="p">,</span><span class="w">
</span><span class="nt">"description"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nt">"main"</span><span class="p">:</span><span class="w"> </span><span class="s2">"index.js"</span><span class="p">,</span><span class="w">
</span><span class="nt">"scripts"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nt">"watch"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webpack -d --watch"</span><span class="p">,</span><span class="w">
</span><span class="nt">"build"</span><span class="p">:</span><span class="w"> </span><span class="s2">"webpack"</span><span class="p">,</span><span class="w">
</span><span class="nt">"serve"</span><span class="p">:</span><span class="w"> </span><span class="s2">"serve ./public"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nt">"author"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nt">"license"</span><span class="p">:</span><span class="w"> </span><span class="s2">"MIT"</span><span class="p">,</span><span class="w">
</span><span class="nt">"devDependencies"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nt">"babel-core"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^6.18.2"</span><span class="p">,</span><span class="w">
</span><span class="nt">"babel-loader"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^6.2.9"</span><span class="p">,</span><span class="w">
</span><span class="nt">"babel-preset-es2015"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^6.18.0"</span><span class="p">,</span><span class="w">
</span><span class="nt">"babel-preset-react"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^6.16.0"</span><span class="p">,</span><span class="w">
</span><span class="nt">"serve"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^1.4.0"</span><span class="p">,</span><span class="w">
</span><span class="nt">"webpack"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^1.14.0"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nt">"dependencies"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nt">"axios"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^0.15.3"</span><span class="p">,</span><span class="w">
</span><span class="nt">"cloudinary-react"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^1.0.1"</span><span class="p">,</span><span class="w">
</span><span class="nt">"react"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^15.4.1"</span><span class="p">,</span><span class="w">
</span><span class="nt">"react-dom"</span><span class="p">:</span><span class="w"> </span><span class="s2">"^15.4.1"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre>
</div>
<p>React (and React DOM) must be used since we are making a React app. The <code class="highlighter-rouge">cloudinary-react</code> dependency is Cloudinary’s React SDK, which we will soon see how it works. <code class="highlighter-rouge">axios</code> is a tool for making HTTP requests and, in our case, we will use it request images from the Cloudinary server.</p>
<div class="language-bash highlighter-rouge">
<pre class="highlight"><code><span class="c"># Install dependencies</span>
npm install
</code></pre>
</div>
<h3>2. Setup Webpack</h3>
<p>Webpack is our build tool. Only minimal settings are required to have a build running and our React app compiling:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="c1">// ./webpack.config.js</span>
<span class="kd">var</span> <span class="nx">webpack</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'webpack'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'path'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">BUILD_DIR</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="s1">'public'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">APP_DIR</span> <span class="o">=</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="s1">'src'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">config</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">entry</span><span class="p">:</span> <span class="nx">APP_DIR</span> <span class="o">+</span> <span class="s1">'/index.jsx'</span><span class="p">,</span>
<span class="na">output</span><span class="p">:</span> <span class="p">{</span>
<span class="na">path</span><span class="p">:</span> <span class="nx">BUILD_DIR</span><span class="p">,</span>
<span class="na">filename</span><span class="p">:</span> <span class="s1">'bundle.js'</span>
<span class="p">},</span>
<span class="na">module</span> <span class="p">:</span> <span class="p">{</span>
<span class="na">loaders</span> <span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">test</span> <span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">jsx</span><span class="se">?</span><span class="sr">/</span><span class="p">,</span>
<span class="na">include</span> <span class="p">:</span> <span class="nx">APP_DIR</span><span class="p">,</span>
<span class="na">loader</span> <span class="p">:</span> <span class="s1">'babel'</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">config</span><span class="p">;</span>
</code></pre>
</div>
<p>Basic configuration - an entry, output and loaders to handle the React <code class="highlighter-rouge">.jsx</code> files.</p>
<h3>3. Entry Points</h3>
<p>We need to create an entry point, as we specified in the Webpack configuration, and another entry point for the browser, which is an <code class="highlighter-rouge">index.html</code> file:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="c1">// ./src/index.jsx</span>
<span class="kr">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">render</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react-dom'</span><span class="p">;</span>
<span class="kr">class</span> <span class="nx">Main</span> <span class="kr">extends</span> <span class="nx">Component</span> <span class="p">{</span>
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span>
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"main"</span><span class="o">></span>
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Scotchage</span><span class="o"><</span><span class="sr">/h1</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">(</span><span class="o"><</span><span class="nx">Main</span> <span class="o">/></span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'container'</span><span class="p">));</span>
</code></pre>
</div>
<div class="language-html highlighter-rouge">
<pre class="highlight"><code><span class="c"><!-- ./public/index.html --></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="c"><!--Stylesheet--></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"style.css"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="c"><!--Container for React rendering--></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"container"</span><span class="nt">></div></span>
<span class="c"><!--Bundled file--></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"bundle.js"</span><span class="nt">></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre>
</div>
<h3>4. Create Cloudinary Account</h3>
<p>You need a Cloudinary account to continue with these examples. Sign up for free and store your credentials safely as shown on the dashboard:</p>
<p><img src="http://imgur.com/HdBYCWr.jpg" alt=""></p>
<h2>Uploading Images</h2>
<p>Before using the React SDK to deliver images from the Cloudinary servers, let’s use the awesome Cloudinary upload widget to upload images. First, we need to add this widget to our <code class="highlighter-rouge">index.html</code>:</p>
<div class="language-html highlighter-rouge">
<pre class="highlight"><code><span class="c"><!-- ./public/index.html --></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
. . .
<span class="nt"></head></span>
<span class="nt"><body></span>
. . .
<span class="c"><!-- UPLOAD WIDGET --></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"//widget.cloudinary.com/global/all.js"</span> <span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"bundle.js"</span><span class="nt">></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre>
</div>
<p>Next, we create a button, attach an event to it and upload an image once the button is clicked:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="kr">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">render</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react-dom'</span><span class="p">;</span>
<span class="kr">class</span> <span class="nx">Main</span> <span class="kr">extends</span> <span class="nx">Component</span> <span class="p">{</span>
<span class="nx">uploadWidget</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">cloudinary</span><span class="p">.</span><span class="nx">openUploadWidget</span><span class="p">({</span> <span class="na">cloud_name</span><span class="p">:</span> <span class="s1">'CLOUD_NAME'</span><span class="p">,</span> <span class="na">upload_preset</span><span class="p">:</span> <span class="s1">'PRESET'</span><span class="p">,</span> <span class="na">tags</span><span class="p">:[</span><span class="s1">'xmas'</span><span class="p">]},</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">(</span>
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"main"</span><span class="o">></span>
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Galleria</span><span class="o"><</span><span class="sr">/h1</span><span class="err">>
</span> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"upload"</span><span class="o">></span>
<span class="o"><</span><span class="nx">button</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">uploadWidget</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="k">this</span><span class="p">)}</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"upload-button"</span><span class="o">></span>
<span class="nx">Add</span> <span class="nx">Image</span>
<span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">(</span><span class="o"><</span><span class="nx">Main</span> <span class="o">/></span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'container'</span><span class="p">));</span>
</code></pre>
</div>
<p>The <code class="highlighter-rouge">uploadWidget</code> member method is the handler invoked by the click event to handle our image upload by calling <code class="highlighter-rouge">cloudinary.openUploadWidget</code>. <code class="highlighter-rouge">openUploadWidget</code> takes a config object and the upload callback handler. The config object must have at least <code class="highlighter-rouge">cloud_name</code> and <code class="highlighter-rouge">upload_preset</code> properties with valid values. You can read more about Cloud Names and Upload Presets.</p>
<p><img src="http://imgur.com/KeMwAtv.jpg" alt=""></p>
<h2>Delivering Images with SDK</h2>
<p>The Cloudinary React SDK has three major components, <strong><code class="highlighter-rouge">Image</code></strong>, <strong><code class="highlighter-rouge">CloudinaryContext</code></strong> and <strong><code class="highlighter-rouge">Transformation</code></strong>:</p>
<ul>
<li>
<strong>Image</strong>: This component is responsible for the actual delivery of images. It takes the image ID and asks the server for this image. When the image is provided, it is also responsible for painting the image on the browser.</li>
<li>
<strong>Transformation</strong>: This component is used to apply transformations to images delivered with <code class="highlighter-rouge">Image</code>.</li>
<li>
<strong>CloudinaryContext</strong>: You can specify Cloudinary configuration for each image on the <code class="highlighter-rouge">Image</code> component. This can be tedious when you are dealing with multiple images. <code class="highlighter-rouge">CloudinaryContext</code> allows you to apply configuration to a group of <code class="highlighter-rouge">Image</code>s.</li>
</ul>
<p>Most times you would end up with a structure like this:</p>
<div class="language-html highlighter-rouge">
<pre class="highlight"><code><span class="nt"><CloudinaryContext></span>
<span class="nt"><Image></span>
<span class="nt"><Transformation</span> <span class="nt">/></span>
<span class="nt"><Transformation</span> <span class="nt">/></span>
<span class="nt"></Image></span>
<span class="nt"><Image></span>
<span class="nt"><Transformation</span> <span class="nt">/></span>
<span class="nt"></Image></span>
<span class="nt"></CloudinaryContext></span>
</code></pre>
</div>
<p>Back to our demo app, we can request an image from the Cloudinary server and display it with the following components:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="kr">import</span> <span class="nx">React</span><span class="p">,</span> <span class="p">{</span> <span class="nx">Component</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">axios</span> <span class="nx">from</span> <span class="s1">'axios'</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">CloudinaryContext</span><span class="p">,</span> <span class="nx">Transformation</span><span class="p">,</span> <span class="nx">Image</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'cloudinary-react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="p">{</span> <span class="nx">render</span> <span class="p">}</span> <span class="nx">from</span> <span class="s1">'react-dom'</span><span class="p">;</span>
<span class="kr">class</span> <span class="nx">Main</span> <span class="kr">extends</span> <span class="nx">Component</span> <span class="p">{</span>
<span class="nx">constructor</span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">super</span><span class="p">(</span><span class="nx">props</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">gallery</span><span class="p">:</span> <span class="p">[]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">componentDidMount</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// Request for images tagged xmas </span>
<span class="nx">axios</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'http://res.cloudinary.com/christekh/image/list/xmas.json'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">res</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">res</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">resources</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="na">gallery</span><span class="p">:</span> <span class="nx">res</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">resources</span><span class="p">});</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">uploadWidget</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// . . .</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">(</span>
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"main"</span><span class="o">></span>
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Galleria</span><span class="o"><</span><span class="sr">/h1</span><span class="err">>
</span> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"gallery"</span><span class="o">></span>
<span class="o"><</span><span class="nx">CloudinaryContext</span> <span class="nx">cloudName</span><span class="o">=</span><span class="s2">"CLOUDNAME"</span><span class="o">></span>
<span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">gallery</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span>
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"responsive"</span> <span class="nx">key</span><span class="o">=</span><span class="p">{</span><span class="nx">data</span><span class="p">.</span><span class="nx">public_id</span><span class="p">}</span><span class="o">></span>
<span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"img"</span><span class="o">></span>
<span class="o"><</span><span class="nx">a</span> <span class="nx">target</span><span class="o">=</span><span class="s2">"_blank"</span> <span class="nx">href</span><span class="o">=</span><span class="p">{</span><span class="err">`</span><span class="na">http</span><span class="p">:</span><span class="c1">//res.cloudinary.com/christekh/image/upload/${data.public_id}.jpg`}></span>
<span class="o"><</span><span class="nx">Image</span> <span class="nx">publicId</span><span class="o">=</span><span class="p">{</span><span class="nx">data</span><span class="p">.</span><span class="nx">public_id</span><span class="p">}</span><span class="o">></span>
<span class="o"><</span><span class="nx">Transformation</span>
<span class="nx">crop</span><span class="o">=</span><span class="s2">"scale"</span>
<span class="nx">width</span><span class="o">=</span><span class="s2">"300"</span>
<span class="nx">height</span><span class="o">=</span><span class="s2">"200"</span>
<span class="nx">dpr</span><span class="o">=</span><span class="s2">"auto"</span>
<span class="nx">responsive_placeholder</span><span class="o">=</span><span class="s2">"blank"</span>
<span class="o">/></span>
<span class="o"><</span><span class="sr">/Image</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/a</span><span class="err">>
</span> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"desc"</span><span class="o">></span><span class="nx">Created</span> <span class="nx">at</span> <span class="p">{</span><span class="nx">data</span><span class="p">.</span><span class="nx">created_at</span><span class="p">}</span><span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="p">)</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="o"><</span><span class="sr">/CloudinaryContext</span><span class="err">>
</span> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"clearfix"</span><span class="o">><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">(</span><span class="o"><</span><span class="nx">Main</span> <span class="o">/></span><span class="p">,</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">'container'</span><span class="p">));</span>
</code></pre>
</div>
<p>Take one more look at the upload code:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code> <span class="nx">cloudinary</span><span class="p">.</span><span class="nx">openUploadWidget</span><span class="p">({</span> <span class="na">cloud_name</span><span class="p">:</span> <span class="s1">'christekh'</span><span class="p">,</span> <span class="na">upload_preset</span><span class="p">:</span> <span class="s1">'idcidr0h'</span><span class="p">,</span> <span class="na">tags</span><span class="p">:[</span><span class="s1">'xmas'</span><span class="p">]},</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="p">.</span> <span class="p">.</span> <span class="p">.</span>
</code></pre>
</div>
<p>Each image is tagged with <code class="highlighter-rouge">xmas</code>, which serves as a way to request images with this tag as a collection. This is exactly what we are using the <code class="highlighter-rouge">axios</code> library to do when the component mounts:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="nx">axios</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'http://res.cloudinary.com/CLOUDNAME/image/list/xmas.json'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">res</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">res</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">resources</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="na">gallery</span><span class="p">:</span> <span class="nx">res</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">resources</span><span class="p">});</span>
<span class="p">});</span>
</code></pre>
</div>
<p><code class="highlighter-rouge">axios</code> uses promises, so whenever the promise resolves in our case, we have a payload of images. We take advantage of React state to update our UI with the fetched resources.</p>
<p>Down to rendering, we configure the <code class="highlighter-rouge">CloudinaryContext</code> with our <code class="highlighter-rouge">cloud_name</code>, iterate over the <code class="highlighter-rouge">gallery</code> state that stores the images and displays them using the <code class="highlighter-rouge">Image</code> component. We also apply few transformations using the <code class="highlighter-rouge">Transformation</code> component.</p>
<blockquote>
<p>For security reasons, Cloudinary will not allow you to make such request from the client unless you tell it to. The best way to go is to use the admin API via a backend SDK and then send the resource list to the client.</p>
</blockquote>
<p><img src="http://imgur.com/uCKacWp.jpg" alt=""></p>
<h2>Updating State with New Uploads</h2>
<p>We are able to upload images and request for images to be displayed on the user’s browsers. Here is how we update the displayed images instantly when the user uploads a new image:</p>
<div class="language-js highlighter-rouge">
<pre class="highlight"><code><span class="nx">uploadWidget</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">_this</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">cloudinary</span><span class="p">.</span><span class="nx">openUploadWidget</span><span class="p">({</span> <span class="na">cloud_name</span><span class="p">:</span> <span class="s1">'CLOUDNAME'</span><span class="p">,</span> <span class="na">upload_preset</span><span class="p">:</span> <span class="s1">'PRESET'</span><span class="p">,</span> <span class="na">tags</span><span class="p">:[</span><span class="s1">'xmas'</span><span class="p">]},</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span> <span class="nx">result</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Update gallery state with newly uploaded image</span>
<span class="nx">_this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span><span class="na">gallery</span><span class="p">:</span> <span class="nx">_this</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">gallery</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">result</span><span class="p">)})</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Rather than logging the uploaded image information to the console, we update the <code class="highlighter-rouge">gallery</code> state, which bears the list of requested images, by concatenating the uploaded result to the <code class="highlighter-rouge">gallery</code>.</p>
<h2>Image Management Simplified</h2>
<p>Image uploads, transformation and delivery has never been easier. These tasks have been a serious challenge for developers. Cloudinary has created a way to abstract all this hard work, enabling you to simply plug and play.</p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/react-native-exponent-with-charlie-cheever">Native's Exponent with Charlie Cheever</a></h1><div class="_107uo">
<p>React Native continues on a development spree in late 2016. With an ambitious two-week release cycle, the framework makes rapid progress towards feature and performance parity with its native Android and iOS equivalents. At the same time, these quick release periods frequently introduce breaking changes, difficulty with setup, and challenges with basic configuration.</p>
<p>Enter Exponent, a tool that promises easier setup, development, and deployment of React Native applications. Rather than being a replacement for React Native, as it is sometimes confused, Exponent augments React Native by dramatically simplifying the development and deployment processes. Whereas basic setup with an Android environment to develop with React Native can take over an hour by hand, even for experienced engineers, Exponent shortens the time to start to “Hello World” to a handful of minutes.</p>
<!--more-->
<p>React Native continues on a development spree in late 2016. With an ambitious two-week release cycle, the framework makes rapid progress towards feature and performance parity with its native Android and iOS equivalents. At the same time, these quick release periods frequently introduce breaking changes, difficulty with setup, and challenges with basic configuration.</p>
<p>Enter Exponent, a tool that promises easier setup, development, and deployment of React Native applications. Rather than being a replacement for React Native, as it is sometimes confused, Exponent augments React Native by dramatically simplifying the development and deployment processes. Whereas basic setup with an Android environment to develop with React Native can take over an hour by hand, even for experienced engineers, Exponent shortens the time to start to “Hello World” to a handful of minutes.</p>
<p><a href="https://getexponent.com/">Exponent’s</a> prime feature is revealed as it’s namesake IDE. The Exponent IDE is development platform for not only developing apps to test in their respective environment simulators, but also simplifies testing them on real devices.</p>
<p>One of the cofounders of Exponent, <a href="https://twitter.com/ccheever">Charlie Cheever</a>, agreed to answer a few questions about Exponent and its purpose in the community.</p>
<hr>
<p><strong>Hi, Charlie. Congrats on the release of Exponent! One of the toughest aspects of Exponent is understanding what its purpose is. What is the primary goal of Exponent?</strong></p>
<p>Thanks :)</p>
<p>Before I worked on mobile software, I spent about 15 years making websites. When I started working on the Quora iPhone app and Android app, it felt like time traveling back to 1993. So many things to worry about that have nothing to do with the product you want to build.</p>
<p>One thing we’re trying to do with Exponent is making it as easy to develop native mobile apps as it is to make websites, or even easier! I think about how I learned to build software as a kid–making games on my TI-85 and making Hypercard stacks–and I want to make it so that the middle school kids of today can make cool stuff for themselves and their friends.</p>
<p><strong>Basic environment setup of the iOS and Android simulators for developing React Native apps is commonly cited as a headache by new developers. What does Exponent do to alleviate this pain?</strong></p>
<p>The biggest thing that Exponent does is take care of everything related to native code for you. So you don’t need to know Swift/Obj-C/Java or even have Xcode or Android Studio to be able to write React Native apps. You write just JavaScript and Exponent has everything else already setup for you.</p>
<p>Since you don’t write any native code with Exponent, just JavaScript, Exponent has a lot of the most popular native modules built in. Native maps, push notifications, Facebook and Google login, camera and camera roll access, contacts, TouchID, and a native video player are all included among other things. We’re always adding more of these as well. We just added full OpenGL support last week and did a game jam and made some mini games with it and are adding sound soon.</p>
<p>We sometimes talk about Exponent as being like Rails for React Native. You could write a website in Ruby on your own. but Rails sets up a bunch of sensible things right off that bat that work together in a coherent way and we kind of do the same thing for React Native. Exponent includes instant app updating as a default, so you can deploy new code and assets with one command in seconds, even faster than most websites can be deployed.</p>
<p><strong>Even after getting set up with the Android and iOS simulators, testing a React Native app on a real phone can still be a challenge. How does Exponent make it easier to share apps in progress with would-be users?</strong></p>
<p>You can actually open any Exponent project that you’re working on in our development app right away. When you develop with Exponent, you get a URL for your project, and you can open that URL on any phone with the Exponent developer app which you can download from the iOS App Store or Google Play Store. You don’t need to jack your phone into your computer–just open the URL.</p>
<p>Another really cool thing about this is that, if you’re working with someone else, you can just send them the URL and they can open it on their phone as well, even if they are halfway around the world.</p>
<p>We’ve done a bunch of work to make this pretty nice, like having <code class="highlighter-rouge">console.log</code> work even if the phone running your code isn’t plugged into your computer. And you can, of course, open your project on the iOS Simulator or an Android Emulator as well if you prefer.</p>
<p>I know you mentioned a lot of people have trouble getting React Native setup on Android especially. With Exponent, every project works on both iOS and Android from the start and you never have to deal with Android Studio, so the process of getting going is much easier.</p>
<p><strong>What type, or genre, of application would be a good fit with React Native and Exponent?</strong></p>
<p>I would actually use React Native for almost any mobile app at this point. Doing development the traditional way (writing Swift/Java/Obj-C code) is just too hard to iterate on when you consider the slowness of the code-compile-copy-run loop and the fact that you have to write your app twice (and then keep it in sync!). The other thing that is an absolutely huge deal here but is sometimes overlooked is the layout engine. It’s much easier to build and change a layout in React Native’s Flexbox than any of the UI libraries that I’ve seen for Java/Swift/Obj-C.</p>
<p>And if you need to do something really intense, like Snapchat live video filters, you can just write your own code as a native module and write the rest of your app in JS.</p>
<p>I would use Exponent for anything I could because it just saves a lot of time and headaches since you don’t need to deal with Android Studio or Xcode. Some people don’t know that you can turn an Exponent project into an app store app for iOS or for Android with just one command.</p>
<p>In general, Exponent will work for you in pretty much every case where just having a mobile website is one of the things that you’re considering. The features are pretty equivalent except that Exponent apps feel like native apps and mobile apps still feel like mobile web apps.</p>
<p>The main reason <em>not</em> to use Exponent is if you have some custom native code that you need that isn’t included with Exponent. The most common reasons that people can’t use Exponent are if they need use Bluetooth or HealthKit or something else low level that isn’t built in to Exponent; or if they need to integrate into an existing project (though we are working right now on a solution that will let you do this).</p>
<p>The exception to all this is games. If you are making a mobile game, Unity is probably the best choice for you. But we did add OpenGL support to Exponent recently and had a game jam and I was surprised at how good some of the entries were, so I think that might change.</p>
<p>TL;DR: For apps that aren’t games, always use React Native (if you need to do something super custom, just do it as a native module). If you can, use Exponent (you can most of the time but check our docs to make sure we’re not missing anything you need).</p>
<p><strong>One aspect of React Native that seems to be undergoing constant flux is its solution for navigation. Between the built in Navigators and open source solutions, do you have any thoughts on an ideal solution for navigation?</strong></p>
<p>Short version: I think you should use Ex-Navigation that Adam Miskiewicz (skevy) and Brent Vatne on our team wrote. Skevy in particular has been thinking about navigation in mobile apps and React Native for a long time. Using Ex-Navigation is definitely a better idea than Navigator or NavigatorIOS.</p>
<p>To make things confusing, there is also NavigatorExperimental (yes, that’s different from Ex-Navigation) and ExNavigator (which was made by James Ide and Ex-Navigation is based on). The good news is that everyone working on these problems got together and decided to merge them all together. I don’t know how long that is going to take but it will probably be released sometime in the next few months under the name React Navigation, and that should unify everyone’s efforts!</p>
<p>There is also this other school of thought where some people like to use the platform-specific native code for navigation which is the approach that the Wix Navigator uses. I have a strong personal view that its preferable to write UI components like this in JS because I actually think you want your app to be the same across iOS and Android (they are both just black rectangles with touch screens!) and JS tends to make your code more composable and customizable.</p>
<p>Use Ex-Navigation and keep an eye out for React Navigation! Use JS instead of native for this UI code!</p>
<p><strong>Given the increasingly fast development and deployment times, handling API setup for dealing with data is becoming a large obstacle to React Native apps. Do you have any thoughts about the use of Backend-As-A-Service solutions like Firebase compared to rolling your own API with Node/Express, Rails, or similar?</strong></p>
<p>I don’t have a strongly held view on this right now. There are so many solutions that fit the use cases of people with different needs. We’re seeing things getting easier and easier in every direction that you look.</p>
<p>If you want to write your own code and you’re using JS, you can use something like Zeit’s new <code class="highlighter-rouge">now</code> stuff to deploy essentially instantly. If you want a more general purpose solution, Heroku is also really easy. And then of course there is AWS and Google Cloud, etc.</p>
<p>It’s trivially easy for React Native apps to communicate with essentially any backend that uses HTTP/JSON since <code class="highlighter-rouge">fetch</code> and <code class="highlighter-rouge">JSON.parse</code> are built-in.</p>
<p>If you don’t want to write any code, it seems like Firebase has become the most popular solution since Parse announced its shutdown. One nice thing about Firebase is that you can use their hosted database stuff with React Native using just JS, which means it works just fine with Exponent. Someone wrote up a guide to how to do this here: <a href="https://gist.github.com/sushiisumii/d2fd4ae45498592810390b3e05313e5c">https://gist.github.com/sushiisumii/d2fd4ae45498592810390b3e05313e5c</a></p>
<p>Longer term, it seems like something like GraphQL/Relay should become really popular, but that stuff is too hard to setup and use still to be mainstream just yet. I’m not sure whether it will be GraphQL/Relay maturing and getting revised that wins or something else that is slightly different and easy to think about as a developer that comes and beats it, but directionally, it’s definitely right. We built something like this at Quora and it saved a ton of development time.</p>
<p>I would just use whatever you are most comfortable with – almost anything will work! React Native is really similar to the the web in terms of its client capabilities and so I would just think about a React Native or Exponent app as being mostly like a website.</p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/routing-in-react-native-with-jake-murzy">Routing in React Native with Jake Murzy</a></h1><div class="_107uo">
<p>Jake Murzy has been hard at work creating a new navigational library for React Native over the last couple of months. While React JS has the benefit of the highly-regarded React Router, such a comprehensive routing solution doesn’t exist yet in the React Native community. In fact, React Native’s routing landscape has been in constant upheaval for the last year. The library itself has official three ‘navigators’ for handling decision making on which components to show the user, including ‘NavigatorIOS’, ‘Navigator’, and - more recently - ‘NavigatorExperimental’. The open source community likewise has the packages ‘React Native Router Flux’, ‘React Native Router Native’, and ‘React Native Redux Router’, which of which are in various states of completion, or, more commonly, disrepair.</p>
<!--more-->
<p>Jake Murzy has been hard at work creating a new navigational library for React Native over the last couple of months. While React JS has the benefit of the highly-regarded React Router, such a comprehensive routing solution doesn’t exist yet in the React Native community. In fact, React Native’s routing landscape has been in constant upheaval for the last year. The library itself has official three ‘navigators’ for handling decision making on which components to show the user, including ‘NavigatorIOS’, ‘Navigator’, and - more recently - ‘NavigatorExperimental’. The open source community likewise has the packages ‘React Native Router Flux’, ‘React Native Router Native’, and ‘React Native Redux Router’, which of which are in various states of completion, or, more commonly, disrepair.</p>
<p><a href="https://github.com/jmurzy/react-router-native">React Router Native</a> appears to focus on matching the API of the immensely popular React Router package, even going as far as introducing the concept of a URL into React Native, which bucks the notion that only web applications need or deserve a URL.</p>
<hr>
<p><strong>Today Jake is going to share some of his thoughts about his new library.</strong></p>
<p><strong>Q: Hi Jake! The React Native library contains several navigation solutions and the surrounding ecosystem has multiple routing libraries. What made you decide to make your own?</strong></p>
<p>Hey! Thanks for reaching out. I’ve been eagerly watching what’s happening with navigation on React Native for a while. Until very recently, the whole Navigation scene in React Native was a mess. Navigator was being deprecated in favor of NavigationExperimental and NavigationExperimental wasn’t ready for prime time.</p>
<p>My team was just starting a new project so I tried quite a few of the available solutions. Having successfully used React Router on the web, we were looking for a similar solution. Unfortunately, React Router did not support React Native, and other solutions we found were either very unstable, had a hard time keeping up with upstream changes on each release or the quality of code was quite poor.</p>
<p>NavigationExperimental did most of what we wanted but it was a bit too low level so often times we found ourselves writing navigation related code and you can imagine how this gets tedious fast. The low level nature of NavigationExperimental is really by design to allow abstractions to be built up in higher layers. So to finally answer your question, the project came directly out of my frustration trying to make navigation work on React Native as good as React Router did on the web.</p>
<p><strong>Q: What is the strength of your routing system? Is there any type of app that would be a perfect fit with React Router Native? Conversely, is there any type of app that <em>wouldn’t</em> be a good fit with the library?</strong></p>
<p>The use cases for React Router Native is pretty much the same as NavigationExperimental—which is the only supported navigation library by the React Native team. React Router Native is a very thin layer on top of NavigationExperimental that offers React Router’s mental model in a native app. Under the hood, it uses React Router for routing and NavigationExperimental for rendering user components. This is a very powerful combination that makes URLs possible on mobile.</p>
<p>Most apps do not have deep-linking capabilities because implementing it for each screen in your app is a challenging task. Even within apps, users are often forced to take screenshots to share information. And for many, it’s vital that their apps support deep-linking. For example, Yelp goes as far to show a share prompt when users take screenshots of business listings. React Router Native enables developers to implement deep-linking in their apps without putting forth much effort. This can pave the way for a more connected app ecosystem.</p>
<p>That being said, we’re still in the early days of React Native figuring out the right abstractions. Navigation on mobile is a challenging task, and having different flavors is only healthier as the community weighs the pros and cons of each approach rather than second guessing best-practices. So I’m hoping to get the community involved to shape the direction of the project.</p>
<p><strong>Q: Is React Router Native designed to be used with any of the official Navigation components written by the React Native team?</strong></p>
<p>Absolutely. One of the primary goals of the project is that we follow React’s “learn once, write anywhere” principle. So you can use the community maintained components, interpolators and pan responders from React Native, and everything is highly customizable if you need instruct NavigationExperimental to do fancy transition animations, etc.</p>
<p><strong>Q: The React Router team has somewhat famously rewritten their API several times in the last two years, each time introducing several breaking changes. Do you hope to keep your library at parity with React Router, breaking changes and all? Case in point, the V4 release of React Router will introduce an all-new API.</strong></p>
<p>React Router v4 is a complete rewrite. There was a lot of head-scratching on Twitter over the entire new set of breaking changes. Many people thought v4 should at best have been released under a different name. I’m not sure if I agree with that sentiment though, I understand where it is coming from. React Router v4 is a preview release, and in my opinion, it’s really hard to argue against replacing a foreign API with simple React components. I do hope to keep the library at parity with React Router, and to be honest, v4’s new everything-is-a-component approach makes the integration even easier. So over the next few weeks I’ll be working on v4 support.</p>
<p><strong>Q: If you were new to React Native, which routing solution would you use? Why?</strong></p>
<p>This is a hard one to answer. Eric Vicenti has done a great job on NavigationExperimental and most of the issues have been sorted out by the community over the last few months. So if you’re familiar with Redux concepts and comfortable writing your own reducers to manage navigation state, NavigationExperimental is a great choice.</p>
<p>One that I’m surprised you didn’t mention that deserves more attention is ExNavigation—another fairly new addition to the brewery. It also uses NavigationExperimental and is maintained by Adam Miskiewicz, Brent Vatne and other awesome members of the Exponent community. It feels a bit tied to the Exponent platform, but runs perfectly fine on React Native and is open source. So you’ve got that.</p>
<p>Finally, If you’re just getting started with React Native and all you need is to be able to click a button and have it transition to a different scene but you don’t want it to get in your way when you need to reach in and apply complex navigational patterns, I strongly recommend you take React Router Native for a spin.</p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/playing-with-react-and-d3">Playing With React and D3</a></h1><div class="_107uo">
<p>D3 is great at data visualizations, but it manipulates the DOM directly to display that data. Rendering DOM elements is where React shines. It uses a virtual representation of the DOM (virtual DOM) and a super performant diffing algorithm in order to determine the fastest way to update the DOM. We want to leverage React’s highly efficient, declarative, and reusable components with D3’s data utility functions.</p>
<!--more-->
<p>At this point, we can safely say that <a href="https://facebook.github.io/react/">React</a> is the preferred JavaScript library for building user interfaces. It is used practically everywhere and is almost as pervasive as <a href="https://jquery.com/">jQuery</a>. It has an API that is simple, powerful, and easy to learn. Its performance metrics are really impressive thanks to the Virtual DOM and its clever <a href="https://facebook.github.io/react/docs/reconciliation.html">diff algorithm</a> between state changes. Nothing, however, is perfect, and React too has its limitations. One of React’s greatest strengths is the ease with which it integrate third-party libraries, but some libraries, especially opinionated ones, are more difficult to integrate than others.</p>
<p>An extremely popular library that can be tricky to integrate with React is <a href="https://d3js.org/">D3.js</a>. D3 is an excellent data visualization library with a rich and powerful API. It is the gold standard of data visualizations. However, Because this library is opinionated about data, it is no trivial endeavour to get it to work with React. A few simple strategies permit these two libraries to work together in very powerful ways.</p>
<p><strong>Editor’s Note</strong>: Check out our upcoming workshop, <a href="http://bit.ly/1T0PG3b">React and D3</a>, a crash course in learning how to create data visualizations with these two in demand libraries. Reserve your spot now on Eventbrite and get 20% off admission. Learn more at the <a href="http://bit.ly/1T0PG3b">Eventbrite page</a></p>
<h2>What is React?</h2>
<p>React is an open-source JavaScript library for creating user interfaces that addresses the challenges of building large applications with data that changes over time. Originally developed at Facebook, it is now seen in many of the most commonly used web applications including Instagram, Netflix, Airbnb, and HelloSign.</p>
<h2>Why is React so popular?</h2>
<p>React helps developers build applications by helping manage the application state. It’s simple, declarative, and composable. React is not a traditional MVC framework because React is really only interested in building user interfaces. Some have called it the “V(iew)” in MVC, but that’s a little misleading. React’s viewpoint is different. As application logic has reoriented toward the client, developers have applied more structure to their front-end JavaScript. We applied a paradigm that we already understood from the server (MVC) to the browser. Of course, the browser environment is very different from the server. React acknowledges that client-side applications are really a collection of UI components that should react to events like user interaction.</p>
<p>React encourages the building applications out of self-contained, reusable components that only care about a small piece of the UI. Other frameworks such as Angular also attempt to do this, but React stands out because it enforces a unidirectional data flow from parent component to child component. This makes debugging much easier. Debugging is the hardest part of application development, so while React is more verbose that other libraries or frameworks, in the end it saves a lot of time. In a framework like Angular’s, it can be hard to figure out where a bug is coming from: The view? The model? The controller? The directive? The directive controller? Data in Angular flows in many different directions, and this makes it hard to reason about that state of your application. In React, when there is a bug (and there will be!), you can quickly determine where the bug originated from because data only moves in one direction. Locating a bug is as simple as connecting the numbered dots until you find the culprit.</p>
<h2>What is D3?</h2>
<p>D3 (Data-Driven Documents) is a JavaScript library for producing dynamic, interactive data-visualizations. It’s fairly low level, and the developer has a lot of control over the end result. It takes a bit of work to get D3 to do what you want, so if you’re looking for a more prepackaged solution, you’re probably better off with highcharts.js. That said, it is fairly simple to pick up once you get the hang of it.</p>
<p>D3 does four main things:</p>
<ol>
<li>LOADS: D3 has convenient methods for importing data from CSV documents.</li>
<li>BINDS: D3 binds data elements to the DOM via JavaScript and SVG.</li>
<li>TRANSFORMS: data can be adjusted to fit your visual requirements</li>
<li>TRANSITIONS: D3 can respond to user input and animate elements based on that input</li>
</ol>
<h2>Why Would We Want To Use React with D3?</h2>
<p>D3 is great at data visualizations, but it manipulates the DOM directly to display that data. Rendering DOM elements is where React shines. It uses a virtual representation of the DOM (virtual DOM) and a super performant diffing algorithm in order to determine the fastest way to update the DOM. We want to leverage React’s highly efficient, declarative, and reusable components with D3’s data utility functions. Also, once we create a chart component, we can want to be able to reuse that chart with different data anywhere in our app.</p>
<h2>How to use React and D3?</h2>
<p>D3, like React, is declarative.D3 uses data binding, whereas React uses a unidirectional data flow paradigm. Getting these two libraries to work together takes a bit of work, but the strategy is fairly simple: since SVG lives in the DOM, let React handle displaying SVG representations of the data and lett D3 handle all the math to render the data.</p>
<p>Of course, we’ll have to make compromises. React is unopinionated and flexible, thereby allowing you to accomplish whatever needs to be done. Some tasks, like creating axes, are tedious. We can let D3 directly access the DOM and create. It handles axes well, and since we only need to create very few, this tactic won’t affect performance.</p>
<p>Let’s go through a simple example. I created a repository you can use to follow along here: <a href="https://github.com/freddyrangel/playing-with-react-and-d3">playing-with-react-and-d3</a>. You can follow in the <code class="highlighter-rouge">unfinished</code> directory and if you get stuck you can take a look at the <code class="highlighter-rouge">finished</code> directory.</p>
<p>Let’s generate a random list of X-Y coordinates and display them on a ScatterPlot chart. If you’re following the tutorial, a finished example is provided for you under the “finished” directory, but you can also follow along under “unfinished.” I’ve gone through the trouble of doing all the setup for you. The build will automatically be created from “unfinished/src/index.jsx”</p>
<p>Let’s start by creating a simple “Hello World!” React component. Create a file under “components” named “chart.jsx”</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/chart.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">export</span> <span class="k">default</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Hello</span><span class="p">,</span> <span class="nx">World</span><span class="o">!<</span><span class="sr">/h1></span><span class="err">;
</span><span class="p">}</span>
</code></pre>
</div>
<p>This example is simple, but let’s go over the explanation anyway. Since we’re rendering a simple H1 with no state, we can just export a function that returns the HTML we expect. If you’re familiar with Angular or Ember, it might look weird to insert HTML directly into our JS code. On the one hand, this goes against everything we’ve learned about unobtrusive JavaScript. But on the other hand, it actually makes sense: we’re not putting JavaScript in our HTML, we’re putting our HTML into our JavaScript. React sees HTML and client-side JavaScript as fundamentally bonded together. They’re both concerned about one thing – rendering UI components to the user. They simply cannot be separated without losing the ability to see what your component is going at a glance. The great benefits of this approach is that you can describe exactly what your component will look like when it’s rendered.</p>
<p>Also, keep in mind that this is only possible with JSX, which translates HTML elements into React functions that will render the HTML to the page.</p>
<p>Now, let’s move on and mount our component to the DOM. Open up “index.jsx”</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/index.jsx</span>
<span class="kr">import</span> <span class="s1">'./main.css'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">ReactDOM</span> <span class="nx">from</span> <span class="s1">'react-dom'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">Chart</span> <span class="nx">from</span> <span class="s1">'./components/chart.jsx'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">mountingPoint</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'div'</span><span class="p">);</span>
<span class="nx">mountingPoint</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="s1">'react-app'</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">mountingPoint</span><span class="p">);</span>
<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o"><</span><span class="nx">Chart</span><span class="o">/></span><span class="p">,</span> <span class="nx">mountingPoint</span><span class="p">);</span>
</code></pre>
</div>
<p>You probably noticed a few things. You might be wondering why we’re requiring a CSS file. We’re using Webpack, which allows us to require CSS files. This is very useful when we modularize both our stylesheets and our JavaScript. We’re also creating a div in which we want to mount our React app. This is just a good practice in case you want to do other things on the page then render a React component. Lastly, we’re calling <code class="highlighter-rouge">render</code> on ReactDOM with 2 arguments, the name of the component and the DOM element we want to mount it on.</p>
<p>Now, let’s install all the dependencies by navigating to the <code class="highlighter-rouge">unfinished</code> directory and running <code class="highlighter-rouge">npm i</code>. Then, fire up the server with <code class="highlighter-rouge">npm run start</code> and go to <code class="highlighter-rouge">localhost:8080</code></p>
<p><img src="https://reactjsnews.com/img/playing-with-react-and-d3/basic_render.png" alt="Basic Render Image"></p>
<p>Awesome! We have rendered our first React component! Let’s do something a little less trivial now.</p>
<p>Let’s compose some functions that will create an array of random data points and then render a <a href="https://en.wikipedia.org/wiki/Scatter_plot">scatter plot</a>. While we’re at it, we’ll add a button to randomize the dataset and trigger a re-render of our app. Let’s open up our <code class="highlighter-rouge">Chart</code> component and add the following:</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/chart.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">ScatterPlot</span> <span class="nx">from</span> <span class="s1">'./scatter-plot'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">styles</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">width</span> <span class="p">:</span> <span class="mi">500</span><span class="p">,</span>
<span class="na">height</span> <span class="p">:</span> <span class="mi">300</span><span class="p">,</span>
<span class="na">padding</span> <span class="p">:</span> <span class="mi">30</span><span class="p">,</span>
<span class="p">};</span>
<span class="c1">// The number of data points for the chart.</span>
<span class="kr">const</span> <span class="nx">numDataPoints</span> <span class="o">=</span> <span class="mi">50</span><span class="p">;</span>
<span class="c1">// A function that returns a random number from 0 to 1000</span>
<span class="kr">const</span> <span class="nx">randomNum</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">);</span>
<span class="c1">// A function that creates an array of 50 elements of (x, y) coordinates.</span>
<span class="kr">const</span> <span class="nx">randomDataSet</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="p">{</span><span class="na">length</span><span class="p">:</span> <span class="nx">numDataPoints</span><span class="p">}).</span><span class="nx">map</span><span class="p">(()</span> <span class="o">=></span> <span class="p">[</span><span class="nx">randomNum</span><span class="p">(),</span> <span class="nx">randomNum</span><span class="p">()]);</span>
<span class="p">}</span>
<span class="kr">export</span> <span class="k">default</span> <span class="kr">class</span> <span class="nx">Chart</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span><span class="p">{</span>
<span class="nx">constructor</span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">{</span>
<span class="kr">super</span><span class="p">(</span><span class="nx">props</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">state</span> <span class="o">=</span> <span class="p">{</span> <span class="na">data</span><span class="p">:</span> <span class="nx">randomDataSet</span><span class="p">()</span> <span class="p">};</span>
<span class="p">}</span>
<span class="nx">randomizeData</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">setState</span><span class="p">({</span> <span class="na">data</span><span class="p">:</span> <span class="nx">randomDataSet</span><span class="p">()</span> <span class="p">});</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">div</span><span class="o">></span>
<span class="o"><</span><span class="nx">h1</span><span class="o">></span><span class="nx">Playing</span> <span class="nx">With</span> <span class="nx">React</span> <span class="nx">and</span> <span class="nx">D3</span><span class="o"><</span><span class="sr">/h1</span><span class="err">>
</span> <span class="o"><</span><span class="nx">ScatterPlot</span> <span class="p">{...</span><span class="k">this</span><span class="p">.</span><span class="nx">state</span><span class="p">}</span> <span class="p">{...</span><span class="nx">styles</span><span class="p">}</span> <span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="nx">div</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"controls"</span><span class="o">></span>
<span class="o"><</span><span class="nx">button</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"btn randomize"</span> <span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span> <span class="o">=></span> <span class="k">this</span><span class="p">.</span><span class="nx">randomizeData</span><span class="p">()}</span><span class="o">></span>
<span class="nx">Randomize</span> <span class="nx">Data</span>
<span class="o"><</span><span class="sr">/button</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/div</span><span class="err">>
</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Since we want our component to manage it’s own state, we need to add a bit more code than was necessary for our previous “Hello World” stateless functional component. Instead of just a function, we’re going to extend <code class="highlighter-rouge">React.Component</code> and describe our component in the <code class="highlighter-rouge">render()</code> method. <code class="highlighter-rouge">render()</code> is the heart of any React component. It describes what our component is supposed to looks like. React will call <code class="highlighter-rouge">render()</code> on initial mount and on every state change.</p>
<p>Inside of <code class="highlighter-rouge">render()</code>, we are both rendering a scatter plot component as if it were an HTML element and setting some properties or “props”. The <code class="highlighter-rouge">...</code> syntax is a convenient JSX and ES2015 spread operator that spreads the attributes of an array or object instead of doing all of that explicitly. For more information check out: <a href="https://facebook.github.io/react/docs/jsx-spread.html">JSX Spread Attributes</a>. We’re going to use <code class="highlighter-rouge">render()</code> to pass our data and a style object that will be used by some of our child components.</p>
<p>In addition, we’re also rendering a button with an <code class="highlighter-rouge">onClick</code> event handler. We’re going to wrap <code class="highlighter-rouge">this.randomizeData()</code> with an arrow function and bind the value of <code class="highlighter-rouge">this</code> to our <code class="highlighter-rouge">Chart</code> component. When the button is clicked, <code class="highlighter-rouge">randomizeData()</code> will call <code class="highlighter-rouge">this.setState()</code> and pass in some new data.</p>
<p>Let’s talk about <code class="highlighter-rouge">this.setState()</code>. If <code class="highlighter-rouge">render()</code> is the heart of a React component, <code class="highlighter-rouge">setState()</code> is the brains of a component. <code class="highlighter-rouge">setState</code> explicitly tells React that we’re changing the state, thereby triggering a re-render of the component and its children. This essentially turns UI components into state machines.</p>
<p>Inside of <code class="highlighter-rouge">setState()</code>, we’re passing an object with <code class="highlighter-rouge">data</code> set to the <code class="highlighter-rouge">randomDataSet()</code>. This means that if we want to retrieve the state of our application, we need only call <code class="highlighter-rouge">this.state.whateverStateWereLookingFor</code>. In this case, we can retrieve the randomData by calling <code class="highlighter-rouge">this.state.data</code>.</p>
<p>A little side note on how React works: React offers great performance for rendering UI components by implementing a diff algorithm and comparing a virtual DOM in memory with the actual DOM. When you think about it, the DOM is really a large tree structure. If there’s one thing we have learned from decades of computer science research, it’s how to compare and manipulate trees. React takes advantage of clever tree diffing algorithms, but in order to work, each component can only render one parent element (i.e., you cannot render sibling elements). That’s why In the render function we’re wrapping all our elements in one parent div.</p>
<p>Let’s get started with the scatter plot component. Create a file <code class="highlighter-rouge">unfinished/src/components/scatter-plot.jsx</code> :</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/scatter-plot.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">d3</span> <span class="nx">from</span> <span class="s1">'d3'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">DataCircles</span> <span class="nx">from</span> <span class="s1">'./data-circles'</span><span class="p">;</span>
<span class="c1">// Returns the largest X coordinate from the data set</span>
<span class="kr">const</span> <span class="nx">xMax</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="nx">d3</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">(</span><span class="nx">d</span><span class="p">)</span> <span class="o">=></span> <span class="nx">d</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="c1">// Returns the highest Y coordinate from the data set</span>
<span class="kr">const</span> <span class="nx">yMax</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="nx">d3</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="p">(</span><span class="nx">d</span><span class="p">)</span> <span class="o">=></span> <span class="nx">d</span><span class="p">[</span><span class="mi">1</span><span class="p">]);</span>
<span class="c1">// Returns a function that "scales" X coordinates from the data to fit the chart</span>
<span class="kr">const</span> <span class="nx">xScale</span> <span class="o">=</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">scale</span><span class="p">.</span><span class="nx">linear</span><span class="p">()</span>
<span class="p">.</span><span class="nx">domain</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="nx">xMax</span><span class="p">(</span><span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">)])</span>
<span class="p">.</span><span class="nx">range</span><span class="p">([</span><span class="nx">props</span><span class="p">.</span><span class="nx">padding</span><span class="p">,</span> <span class="nx">props</span><span class="p">.</span><span class="nx">width</span> <span class="o">-</span> <span class="nx">props</span><span class="p">.</span><span class="nx">padding</span> <span class="o">*</span> <span class="mi">2</span><span class="p">]);</span>
<span class="p">};</span>
<span class="c1">// Returns a function that "scales" Y coordinates from the data to fit the chart</span>
<span class="kr">const</span> <span class="nx">yScale</span> <span class="o">=</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">scale</span><span class="p">.</span><span class="nx">linear</span><span class="p">()</span>
<span class="p">.</span><span class="nx">domain</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="nx">yMax</span><span class="p">(</span><span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">)])</span>
<span class="p">.</span><span class="nx">range</span><span class="p">([</span><span class="nx">props</span><span class="p">.</span><span class="nx">height</span> <span class="o">-</span> <span class="nx">props</span><span class="p">.</span><span class="nx">padding</span><span class="p">,</span> <span class="nx">props</span><span class="p">.</span><span class="nx">padding</span><span class="p">]);</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="k">default</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="nx">scales</span> <span class="o">=</span> <span class="p">{</span> <span class="na">xScale</span><span class="p">:</span> <span class="nx">xScale</span><span class="p">(</span><span class="nx">props</span><span class="p">),</span> <span class="na">yScale</span><span class="p">:</span> <span class="nx">yScale</span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">};</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">svg</span> <span class="nx">width</span><span class="o">=</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">width</span><span class="p">}</span> <span class="nx">height</span><span class="o">=</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">height</span><span class="p">}</span><span class="o">></span>
<span class="o"><</span><span class="nx">DataCircles</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="p">{...</span><span class="nx">scales</span><span class="p">}</span> <span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/svg</span><span class="err">>
</span><span class="p">}</span>
</code></pre>
</div>
<p>There’s a lot going on here, so let’s start with the stateless functional component that we’re exporting. D3 uses SVG to render data visualizations. D3 has special methods for creating SVG elements and binding data to those elements – but we’re going to let React handle that. We’re creating an SVG element with the properties passed in by the <code class="highlighter-rouge">Chart</code> component and which can be accessed via <code class="highlighter-rouge">this.props</code>. Then we’re creating a <code class="highlighter-rouge">DataCircles</code> component (more on that below) which will render the points for the scatter plot.</p>
<p>Let’s talk about D3 scales. This is where D3 shines. Scales takes care of the messy math involved in converting your data into a format that can be displayed on a chart. If you have a data point value 189281, but your chart is only 200 pixels wide, then D3 scales converts that value to a number you can use.</p>
<p><code class="highlighter-rouge">d3.scale.linear()</code> returns a linear scale. D3 also supports other types of scales (ordinal, logarithmic, square root, etc.), but we won’t be talking about those here. <code class="highlighter-rouge">domain</code> is short for an “input domain”, i.e., the range of possible input values. It takes an array of the smallest input value possible and the maximum input value. <code class="highlighter-rouge">range</code> on its own is the range of possible output values. So in <code class="highlighter-rouge">domain</code>, we’re setting the range of possible data values from our random data, and in <code class="highlighter-rouge">range</code> we’re telling D3 the range of our chart. <code class="highlighter-rouge">d3.max</code> is a D3 method for determining the maximum value of a dataset. It can take a function which D3 will use to give the max values of the X and Y coordinates.</p>
<p>We use the scales to render the data circles and our axes.</p>
<p>Let’s create the DataCircles component under <code class="highlighter-rouge">unfinished/src/components/data-circles.jsx</code></p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/data-circles.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">renderCircles</span> <span class="o">=</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">coords</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="nx">circleProps</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">cx</span><span class="p">:</span> <span class="nx">props</span><span class="p">.</span><span class="nx">xScale</span><span class="p">(</span><span class="nx">coords</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span>
<span class="na">cy</span><span class="p">:</span> <span class="nx">props</span><span class="p">.</span><span class="nx">yScale</span><span class="p">(</span><span class="nx">coords</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span>
<span class="na">r</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="na">key</span><span class="p">:</span> <span class="nx">index</span>
<span class="p">};</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">circle</span> <span class="p">{...</span><span class="nx">circleProps</span><span class="p">}</span> <span class="sr">/></span><span class="err">;
</span> <span class="p">};</span>
<span class="p">};</span>
<span class="kr">export</span> <span class="k">default</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">g</span><span class="o">></span><span class="p">{</span> <span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">renderCircles</span><span class="p">(</span><span class="nx">props</span><span class="p">))</span> <span class="p">}</span><span class="o"><</span><span class="sr">/g</span><span class="err">>
</span><span class="p">}</span>
</code></pre>
</div>
<p>In this component, we’re rendering a <code class="highlighter-rouge">g</code> element, the SVG equivalent to a <code class="highlighter-rouge">div</code>. Since we want to render a point for every set of X-Y coordinates, were must render multiple sibling elements which we wrap together in a <code class="highlighter-rouge">g</code> element for React to work. Inside of <code class="highlighter-rouge">g</code>, we’re mapping over the data and rendering a circle for each one using <code class="highlighter-rouge">renderCircles</code>. <code class="highlighter-rouge">renderCircles</code> creates an SVG <code class="highlighter-rouge">circle</code> element with a number of properties. Here’s where we’re setting the x and y coordinates (<code class="highlighter-rouge">cx</code> and <code class="highlighter-rouge">cy</code> respectively) with the D3 scales passed in from the scatter plot component. <code class="highlighter-rouge">r</code> is the radius of our circle, and key is something React requires us to do. Since we’re rendering identical sibling components, React’s diffing algorithm needs a way to keep track of them as it updates the DOM over and over. You can use any key you like, as long as it’s unique to the list. Here we’re just going to use the index of each element.</p>
<p>Now, when we look at our browser, we see this:</p>
<p><img src="https://reactjsnews.com/img/playing-with-react-and-d3/plot_points.png" alt="Plot Points Image"></p>
<p>We can see our random data and randomize that data via user input. Awesome! But we’re missing a way to read this data. What we need are axes. Let’s create them now.</p>
<p>Let’s open up <code class="highlighter-rouge">ScatterPlot.jsx</code> and add an <code class="highlighter-rouge">XYAxis</code> component</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/scatter-plot.jsx</span>
<span class="c1">// ...</span>
<span class="kr">import</span> <span class="nx">XYAxis</span> <span class="nx">from</span> <span class="s1">'./x-y-axis'</span><span class="p">;</span>
<span class="c1">// ...</span>
<span class="kr">export</span> <span class="k">default</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="nx">scales</span> <span class="o">=</span> <span class="p">{</span> <span class="na">xScale</span><span class="p">:</span> <span class="nx">xScale</span><span class="p">(</span><span class="nx">props</span><span class="p">),</span> <span class="na">yScale</span><span class="p">:</span> <span class="nx">yScale</span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="p">};</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">svg</span> <span class="nx">width</span><span class="o">=</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">width</span><span class="p">}</span> <span class="nx">height</span><span class="o">=</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">height</span><span class="p">}</span><span class="o">></span>
<span class="o"><</span><span class="nx">DataCircles</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="p">{...</span><span class="nx">scales</span><span class="p">}</span> <span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="nx">XYAxis</span> <span class="p">{...</span><span class="nx">props</span><span class="p">}</span> <span class="p">{...</span><span class="nx">scales</span><span class="p">}</span> <span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/svg</span><span class="err">>
</span><span class="p">}</span>
</code></pre>
</div>
<p>Now, let’s create the <code class="highlighter-rouge">XYAxis</code> component;</p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/x-y-axis.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">Axis</span> <span class="nx">from</span> <span class="s1">'./axis'</span><span class="p">;</span>
<span class="kr">export</span> <span class="k">default</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kr">const</span> <span class="nx">xSettings</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">translate</span><span class="p">:</span> <span class="err">`</span><span class="nx">translate</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">$</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">height</span> <span class="o">-</span> <span class="nx">props</span><span class="p">.</span><span class="nx">padding</span><span class="p">})</span><span class="err">`</span><span class="p">,</span>
<span class="na">scale</span><span class="p">:</span> <span class="nx">props</span><span class="p">.</span><span class="nx">xScale</span><span class="p">,</span>
<span class="na">orient</span><span class="p">:</span> <span class="s1">'bottom'</span>
<span class="p">};</span>
<span class="kr">const</span> <span class="nx">ySettings</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">translate</span><span class="p">:</span> <span class="err">`</span><span class="nx">translate</span><span class="p">(</span><span class="nx">$</span><span class="p">{</span><span class="nx">props</span><span class="p">.</span><span class="nx">padding</span><span class="p">},</span> <span class="mi">0</span><span class="p">)</span><span class="err">`</span><span class="p">,</span>
<span class="na">scale</span><span class="p">:</span> <span class="nx">props</span><span class="p">.</span><span class="nx">yScale</span><span class="p">,</span>
<span class="na">orient</span><span class="p">:</span> <span class="s1">'left'</span>
<span class="p">};</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">g</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"xy-axis"</span><span class="o">></span>
<span class="o"><</span><span class="nx">Axis</span> <span class="p">{...</span><span class="nx">xSettings</span><span class="p">}</span><span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="nx">Axis</span> <span class="p">{...</span><span class="nx">ySettings</span><span class="p">}</span><span class="sr">/</span><span class="err">>
</span> <span class="o"><</span><span class="sr">/g</span><span class="err">>
</span><span class="p">}</span>
</code></pre>
</div>
<p>For simplicity’s sake, we’re creating two objects which will hold the props for each of our X-Y axes. Let’s create an axis component to explain what these props do. Go ahead and create <code class="highlighter-rouge">axis.jsx</code></p>
<div class="language-javascript highlighter-rouge">
<pre class="highlight"><code><span class="c1">// unfinished/src/components/x-y-axis.jsx</span>
<span class="kr">import</span> <span class="nx">React</span> <span class="nx">from</span> <span class="s1">'react'</span><span class="p">;</span>
<span class="kr">import</span> <span class="nx">d3</span> <span class="nx">from</span> <span class="s1">'d3'</span><span class="p">;</span>
<span class="kr">export</span> <span class="k">default</span> <span class="kr">class</span> <span class="nx">Axis</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span>
<span class="nx">componentDidMount</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderAxis</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">componentDidUpdate</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">renderAxis</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">renderAxis</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">node</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">refs</span><span class="p">.</span><span class="nx">axis</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">axis</span> <span class="o">=</span> <span class="nx">d3</span><span class="p">.</span><span class="nx">svg</span><span class="p">.</span><span class="nx">axis</span><span class="p">().</span><span class="nx">orient</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">orient</span><span class="p">).</span><span class="nx">ticks</span><span class="p">(</span><span class="mi">5</span><span class="p">).</span><span class="nx">scale</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">scale</span><span class="p">);</span>
<span class="nx">d3</span><span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="nx">node</span><span class="p">).</span><span class="nx">call</span><span class="p">(</span><span class="nx">axis</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">render</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o"><</span><span class="nx">g</span> <span class="nx">className</span><span class="o">=</span><span class="s2">"axis"</span> <span class="nx">ref</span><span class="o">=</span><span class="s2">"axis"</span> <span class="nx">transform</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">translate</span><span class="p">}</span><span class="o">><</span><span class="sr">/g</span><span class="err">>
</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>Our strategy up to this point has been to let React exclusively handle the DOM. This is a good general rule, but we should leave room for nuance. In this case, the math and work necessary in order to render an axis is quite complicated and D3 has abstracted that pretty nicely. We’re going to let D3 have access to the DOM in this case. And since we’re only going to render a maximum of 2 axis, the trade-off in terms of performance is negligible.</p>
<p>We’re going to create a <code class="highlighter-rouge">g</code> element to hand over to D3 and its DOM manipulation. <code class="highlighter-rouge">transform</code> is an attribute of a <code class="highlighter-rouge">g</code> that defines a list of transform definitions applied to an element and an element’s children. We’re passing in a <code class="highlighter-rouge">translate</code> attribute that moves the <code class="highlighter-rouge">g</code> element to where we want it. SVG is similar to canvas in that x coordinates start at the top rather than at the bottom, so we have to account for this. Otherwise, our X-Axis would be right at the top of the chart. For the Y-Axis, we want to leave some room for rendering the tickmark values.</p>
<p><code class="highlighter-rouge">componentDidMount()</code> is a special React lifecycle method that is called immediately after the React component is mounted on the DOM. It is only called on the initial render. When this component is now rendered on the DOM, we’re going to pass a real DOM node to D3 so it can work its magic. By adding a “ref” attribute to the <code class="highlighter-rouge">g</code> element, we can refer to it later via <code class="highlighter-rouge">this.refs</code>. Every time this component is re-rendered, we want D3 to re-draw the axis. That’s where <code class="highlighter-rouge">componentDidUpdate()</code> comes in. It’s called every time a component is re-rendered. You can learn more about lifecycle methods <a href="https://facebook.github.io/react/docs/component-specs.html">here</a>.</p>
<p>Now, if we take a look at the browser again, we can see the axis, and when we randomize the data, they update automatically to reflect the changes.</p>
<p><img src="https://reactjsnews.com/img/playing-with-react-and-d3/complete_chart.png" alt="Complete Chart Image"></p>
<h2>Conclusion</h2>
<p>This is but a short introduction to React and D3. If you want to learn more check out our upcoming workshop, <a href="http://bit.ly/1T0PG3b">React and D3</a>, a crash course in learning how to create data visualizations with these two in demand libraries. Reserve your spot now on Eventbrite and get 20% off admission. Learn more at the <a href="http://bit.ly/1T0PG3b">Eventbrite page</a></p>
</div></article><article class="-EKGZ"><h1 class="_3GwAp"><a href="https://reactjsnews.com/how-to-make-your-react-apps-10x-faster">How to Make Your React Apps 15x Faster</a></h1><div class="_107uo">
<p>Without any modifications, React is really fast as-is. There are, however, a few things that you can do to improve performance. While working at HelloSign, I discovered some quick fixes that made our apps incredibly snappy. With these simple changes, I was able to reduce render time from over 3000 milliseconds to less than 200 milliseconds.</p>
<!--more-->
<p>Without any modifications, React is really fast as-is. There are, however, a few things that you can do to improve performance. While working at HelloSign, I discovered some quick fixes that made our apps incredibly snappy. With these simple changes, I was able to reduce render time from over 3000 milliseconds to less than 200 milliseconds.</p>
<p><strong>Editor’s Note:</strong></p>
<p>Check out our upcoming <a href="http://www.reactuniversity.com/training">React University Workshops</a>. Our next workshop, <a href="http://www.reactuniversity.com/react-2016" title="React 2016">React 2016</a>, will be held on April 23 at <a href="http://microsoftreactor.com/">Microsoft Reactor</a> in San Francisco and will offer a deep dive into creating modern Single-Page Applications (SPA) using React, Redux, React Router, Immutable.js, and Webpack. Also, if you’re interested in learning the basics about what it takes to be a Data Visualization Engineer, check out <a href="http://www.reactuniversity.com/react-and-d3">React and D3</a>.</p>
<h2>Introduction</h2>
<p>HelloSign is a cloud-based electronic signature tool founded in 2010. As you can imagine, HelloSign is a very JavaScript-heavy codebase. A lot of client-side behavior is necessary to create a rich signing experience. Lately, we’ve moved much of our codebase toward React. In fact, in many places we’ve broken up our codebase into several single-page applications written in React.</p>
<p>Although the HelloSign team was happy with React’s performance before I initially joined the project, I quickly found some low-hanging fruit that could improve runtime speed. Here are the steps you should take to see similar improvements in your own applications.</p>
<h2>Create a Baseline Performance Measurement</h2>
<p>Before you begin, you should take a baseline measurement. Optimizations are meaningless if you can’t verify the results of your modifications.</p>
<p>Thankfully, Chrome has excellent developer tools to help. One, little-used feature of Chrome’s DevTools is the “Timeline” tool. It allows you to record and analyze all activity in your application. You can record interactions on the page, locate potential memory leaks, measure the total time it takes to perform a task, and identify areas of potential <a href="https://developers.google.com/web/fundamentals/performance/rendering/?hl=en">jank</a>. Best of all, the results can be recorded for comparison with your final benchmark.</p>
<p>There’s actually a really awesome video on Chrome’s DevTools that goes into detail about the “Timeline” feature. You can view it <a href="http://forwardjs.com/university/real-time-performance-audit-with-chrome-devtools">here</a>.</p>
<p>We chose to measure the time elapsed between the initial paint of our signer page to the final rendering of the entire page. The initial download of our bundles still needs some optimization, but we’re neither going to mess with nor measure this parameter. It’s fairly easy and consistent to test render time rather than trying to click areas around the page and trying to measure its performance in a repeatable way. Then, all we needed to do was to go to the signer page, open Chrome’s DevTools “Timeline” tab, and refresh the page.</p>
<p>As a side note, make sure that when performing this test, the “Paint” and “Screenshots” boxes are checked so that you can see what the user sees as the page is being rendered.</p>
<p>After all that, we determined that our rendering time from initial paint was a little over 3 seconds. Much too long. Luckily, there was little we had to do to make this quite a bit faster.</p>