This repository was archived by the owner on Sep 3, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjsx-in-depth.html
283 lines (254 loc) · 16.3 KB
/
jsx-in-depth.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="description" content="Composi is a JavaScript library for creating component-based interfaces. It uses the virtual dom to make efficient updates to the DOM based on a component's data or state.">
<meta name="keywords" content="javascript, framework, performance, small, fast, UI, programming, code, component, composi, chocolatechipui, chocolatechip-ui, reactive, virtual dom">
<title>Composi - Tutorials</title>
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/styles.css">
<link rel="stylesheet" href="../css/prism-tomorrow.css">
</head>
<body class='tutorial-page'>
<nav>
<ul class='nav--menu'>
<li class='nav--menu__item'>
<a class='nav--menu__item__link' href="../index.html">
<svg id='composi-logo' viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Composi Logo</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Composi-Logo-Solid" fill="#fff">
<path d="M1.77635684e-15,0 L95,0 L95,38 L209,38 L209,0 L300,0 L300,94 L265,93.8571663 L265,209 L300,209 L300,300 L209,300 L209,265 L95,265 L95,300 L1.77635684e-15,300 L1.77635684e-15,209 L40,209 L40,94 L1.77635684e-15,93.8571663 L1.77635684e-15,0 Z M107,107 L107,192 L192,192 L192,107 L107,107 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
<span class='logo__link--text'>Composi</span></a>
</li>
<li class='nav--menu__item'>
<a class='nav--menu__item__link' href="../docs/installation.html">Docs</a>
</li>
<li class='nav--menu__item selected'>
<a class='nav--menu__item__link' href="./index.html">Tutorials</a>
</li>
<li class='nav--menu__item'>
<a class='nav--menu__item__link external' target='__blank' href="https://github.com/composor/awesome-composi">Resources
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="14px" height="14px" viewBox="0 0 511.626 511.627" style="enable-background:new 0 0 511.626 511.627;"
xml:space="preserve">
<path fill='#fff' d="M392.857,292.354h-18.274c-2.669,0-4.859,0.855-6.563,2.573c-1.718,1.708-2.573,3.897-2.573,6.563v91.361
c0,12.563-4.47,23.315-13.415,32.262c-8.945,8.945-19.701,13.414-32.264,13.414H82.224c-12.562,0-23.317-4.469-32.264-13.414
c-8.945-8.946-13.417-19.698-13.417-32.262V155.31c0-12.562,4.471-23.313,13.417-32.259c8.947-8.947,19.702-13.418,32.264-13.418
h200.994c2.669,0,4.859-0.859,6.57-2.57c1.711-1.713,2.566-3.9,2.566-6.567V82.221c0-2.662-0.855-4.853-2.566-6.563
c-1.711-1.713-3.901-2.568-6.57-2.568H82.224c-22.648,0-42.016,8.042-58.102,24.125C8.042,113.297,0,132.665,0,155.313v237.542
c0,22.647,8.042,42.018,24.123,58.095c16.086,16.084,35.454,24.13,58.102,24.13h237.543c22.647,0,42.017-8.046,58.101-24.13
c16.085-16.077,24.127-35.447,24.127-58.095v-91.358c0-2.669-0.856-4.859-2.574-6.57
C397.709,293.209,395.519,292.354,392.857,292.354z"/>
<path fill='#fff' d="M506.199,41.971c-3.617-3.617-7.905-5.424-12.85-5.424H347.171c-4.948,0-9.233,1.807-12.847,5.424
c-3.617,3.615-5.428,7.898-5.428,12.847s1.811,9.233,5.428,12.85l50.247,50.248L198.424,304.067
c-1.906,1.903-2.856,4.093-2.856,6.563c0,2.479,0.953,4.668,2.856,6.571l32.548,32.544c1.903,1.903,4.093,2.852,6.567,2.852
s4.665-0.948,6.567-2.852l186.148-186.148l50.251,50.248c3.614,3.617,7.898,5.426,12.847,5.426s9.233-1.809,12.851-5.426
c3.617-3.616,5.424-7.898,5.424-12.847V54.818C511.626,49.866,509.813,45.586,506.199,41.971z"/>
</svg></a>
</li>
</ul>
</nav>
<article class='tutorial__article'>
<section>
<div class='tutorial'>
<h1>JSX in Depth</h1>
<p class="tutorial__intro">JSX is just JavaScript. It just happens to look like HTML. A JSX tag is a function that creates an HTML tag with attributes and children.</p>
<p>Let's take an example:</p>
<pre><code class="language-javascript">// functional component:
function Title(title) {
return (
<h1 title='The title'>{title}</h1>
)
}
// The functional component as a custom JSX tag:
<Title {Hello, world!}/>
// The same tag as a hyperscript function:
h('h1', {title: 'The title'}, 'Hello, world!')
// The tag produces the following virtual node:
{
type: "h1",
props: {title: "The title"},
children: ["Hello, world!"]
}
// The virtual node gets converted into a DOM node:
<h1>Hello, world!</h1></code></pre>
<p>JSX is just a simplier way to represent the DOM nodes your component needs to create. Because it is JavaScript, you can use it with normal JavaScript expressions to evaluate and parse the data that you need to display.</p>
<h2>Composition</h2>
<p>Although you can define simple JSX tags, the real strength of JSX is that it lets you you simple JSX elements combined together to create more complex ones. These parts can even be in separate files, allowing for their reuse through your app or in other apps.</p>
<p>As an example of composition, let's create a dialog box. We are going to start with the dialog itself, which is just the border around the content:</p>
<pre><code class="language-javascript">function FancyBorder(props) {
console.log(props)
return (
<div class='FancyBorder FancyBorder-maroon'></div>
)
}
// Inject the dialog in the document:
mount(<FancyBorder />), 'body'</code></pre>
<p>We'll update this to allow the user to pass in the color as a prop:</p>
<pre><code class="language-javascript">function FancyBorder(props) {
console.log(props)
return (
<div class={'FancyBorder FancyBorder-' + props.color}></div>
)
}
// Inject the dialog in the document:
mount(<FancyBorder color="maroon" />,'body')</code></pre>
<p>So, now we have a very basic function component. But we want to be able to render it with a child component. Here is the child:</p>
<pre><code class="language-javascript">function DialogMessage() {
return (
<div>
<h1 class="Dialog-title">Welcome</h1>
<p class="Dialog-message">Thank you for visiting our time machine!</p>
</div>
)
}</code></pre>
<p>Now, the question is, how can we get the child component into the dialog box? As you saw above, we passed the color to the dialog box as a prop. We can do the same with our child component. We'll make a slight modification to FancyBorder so that it can received arbitrary child nodes. We'll do that by passing a second parameter to the function, which we'll call <code>children</code>:</p>
<pre><code class="language-javascript">function FancyBorder(props, children) {
console.log(props)
return (
<div class={'FancyBorder FancyBorder-' + props.color}>
{children}
</div>
)
}</code></pre>
<p>With the <code>FancyBorder</code> component set to capture a <code>children</code> prop, we can pass in our <code>DialogMessage</code> component when we render <code>FancyBorder</code>:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="oGpwVd" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composition" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/oGpwVd/">Composition</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>Through composition we are able to add child components to other components to build more complex solutions.</p>
<h2>Composition with Class Components</h2>
<p>We can use this same technique with class components. We are going to show how to use composition of JSX functional components to create a class component. We are going to start with the same <code>FancyBorder</code> component we made earlier:</p>
<pre><code class="language-javascript">function FancyBorder(props, children) {
console.log(props)
return (
<div class={'FancyBorder FancyBorder-' + props.color}>
{children}
</div>
)
}</code></pre>
<p>We'll use this as the base for our new component. We want to have a dialog where the user can enter a name, and after tapping a button, gets a greeting. By the way, this will be a signup for the Time Travel Program.</p>
<h2>Issues to Deal With</h2>
<p>Because we are going to be passing props down from a class component to child components that are function, there will be some wrapping of the props at each level. Kind of annoying, but its what JSX does in this situation. Therefore we will need to use <code>.props</code> to get at values in places where you would expect too.</p>
<p>Here's the basic setup for our class component:</p>
<pre><code class="language-javascript">class SignUpDialog extends Component {
constructor(props) {
super(props)
this.container = 'section'
this.state = {
login: '',
title:"Time Travel Program",
message:"How should we refer to you?"
}
}
render(props) {
return (
return (
<FancyBorder color='maroon'>
<DialogChildren {...{title: props.title, message: props.message, component: this}}/>
</FancyBorder>
)
}
}</code></pre>
<p>So, we have a class component that returns our <code>FancyBorder</code> component, while passing it props for <code>color</code> and <code>children</code>. Notice how <code>dialogChildren</code> is get passed props and <code>this</code>. That will pass a reference of the class component down to the children so they have access to the parent's properties. In particular we want to expose the parent's state and event methods to the children.</p>
<p>We'll need a component to create the default title and greetign for the dialog. We'll call that component <code>Dialog</code>. We'll also need a component to be the form where the user enters there name an taps a button to submit it. We'll call that <code>FormInputs</code>. Then we'll create a function called <code>dialogChildren</code> which will combine these to. We'll pass this function to the <code>FancyBorder</code> component as its <code>children</code> prop. And, we will add some methods and events to make name submission work. Here is the complete solution:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="vedgVR" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Composition 2" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/vedgVR/">Composition 2</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>As you can see, with some work you can use JSX composition to advantage, even inside a class component.</p>
<h2>Containement</h2>
<p>Another pattern for JSX development is container, where on component contains another. In our previous example we used props to pass in a function that composed several JSX function components together. We can also pass in custom JSX tags for a similar composition pattern. Take a look at the following example. Notice how we have our custom tags defined: <code><Contacts /></code> and <code><Chat /></code>, and that we pass them to the <code>SplitPane</code> tag as its value for left and right:</p>
<p data-height="300" data-theme-id="6688" data-slug-hash="yzvVEx" data-default-tab="js,result" data-user="rbiggs" data-embed-version="2" data-pen-title="Containment" class="codepen">See the Pen <a href="https://codepen.io/rbiggs/pen/yzvVEx/">Containment</a> by Robert Biggs (<a href="https://codepen.io/rbiggs">@rbiggs</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p></p>
<p> </p>
</div>
<aside>
<menu>
<ul class="tutorials__menu">
<li class="tutorials__menu__item">
<a href='./index.html'>Hello World</a>
</li>
<li class="tutorials__menu__item">
<a href='./introducing-jsx.html'>Introducing JSX</a>
</li>
<li class="tutorials__menu__item">
<a href='./rendering-elements.html'>Rendering Elements</a>
</li>
<li class="tutorials__menu__item">
<a href='./components-n-props.html'>Components and Props</a>
</li>
<li class="tutorials__menu__item">
<a href='./state-n-lifecycle.html'>State and Lifecycle</a>
</li>
<li class="tutorials__menu__item">
<a href='./conditional-rendering.html'>Conditional Rendering</a>
</li>
<li class="tutorials__menu__item">
<a href='./handling-events.html'>Handling Events</a>
</li>
<li class="tutorials__menu__item">
<a href='./lists-n-keys.html'>Lists and Keys</a>
</li>
<li class="tutorials__menu__item">
<a href='./forms.html'>Forms</a>
</li>
<li class="tutorials__menu__item">
<a href='./lifting-state-up.html'>Lifting State Up</a>
</li>
<li class="tutorials__menu__item">
<a href='./thinking-in-composi.html'>Thinking in Composi</a>
</li>
<li class="tutorials__menu__item selected">
<a href='./jsx-in-depth.html'>JSX In Depth</a>
</li>
<li class="tutorials__menu__item">
<a href='./advanced-state-management.html'>Advanced State Management</a>
</li>
<li class="tutorials__menu__item">
<a href='./composi-datastore.html'>Composi DataStore</a>
</li>
<li class="tutorials__menu__item">
<a href='./integrating-other-libs.html'>Integrating with Other Libraries</a>
</li>
<li class="tutorials__menu__item">
<a href='./composi-without-jsx.html'>Composi Without JSX</a>
</li>
<li class="tutorials__menu__item">
<a href='./immutable-data.html'>Immutable Data</a>
</li>
</ul>
</menu>
</aside>
</section>
</article>
<footer>
<section>
<svg id='composi-logo-footer' viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Composi Logo</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Composi-Logo-Solid" fill="rgba(255,255,255,0.5)">
<path d="M1.77635684e-15,0 L95,0 L95,38 L209,38 L209,0 L300,0 L300,94 L265,93.8571663 L265,209 L300,209 L300,300 L209,300 L209,265 L95,265 L95,300 L1.77635684e-15,300 L1.77635684e-15,209 L40,209 L40,94 L1.77635684e-15,93.8571663 L1.77635684e-15,0 Z M107,107 L107,192 L192,192 L192,107 L107,107 Z" id="Combined-Shape"></path>
</g>
</g>
</svg>
<h3>Composi is open source (MIT) and available on <a href='https://github.com/composor/composi' target='__blank'>Github</a> and <a href="https://www.npmjs.com/package/composi" target='__blank'>NPM</a>.</h3>
</section>
</footer>
<script src="../js/prism.min.js"></script>
<script src="../js/prism-jsx.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-115293685-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-115293685-1');
</script>
</body>
</html>