When most people get started with React.js, JSX is the first thing that comes as a surprise. JSX is a templating language inside JavaScript. Remeber all those string template you to write with (insert frontend framework here)?, well JSX to the rescue.
Table of Contents:
JSX is a JavaScript syntax extension that looks similar to XML. You can use a simple JSX syntactic transform with React.
Picture this. Instead of writing HTML strings within your code, you can use a preprocessor that allow you to write (basically) pure HTML with some compile-time checking? Brilliant, let's look at the examples from Facebook's Displaying Data post:
Without JSX:
React.createElement('a', {href: 'https://facebook.github.io/react/'}, 'Hello!')
With JSX:
<a href="https://facebook.github.io/react/">Hello!</a>
Great! We've improved readability by 10,000%.
Now that we've got a solid introduction;) to JSX, let's take a look at some common gotchas.
It's common to want to write comments within your markup. Inside of JSX, there are a couple of 'rules' to follow:
{}
valid:
<div>
{/** A comment about the component below */}
<span>Hello, JSX</span>
</div>
invalid:
<div>
/** A comment about the component below */
<span>Hello, JSX</span>
</div>
valid:
<div>
<AwesomeComponent
/** Some commentsabout the props below */
prop1="jsxRocks"
booly={true}
/>
</div>
invalid:
<div>
<AwesomeComponent
{/** Some commentsabout the props below */}
prop1="jsxRocks"
booly={true}
/>
</div>
JSX also makes passing props
(arguments) to other components with
simple HTML-like syntax. If you're not familiar with nesting
components and receiving components, you should check out
JSX In Depth
first.
Normal, string value props are easy to pass to child components:
<AwesomeComponent
name="jsxRocks"
/>
Now inside of AwesomeComponent
you have access to this.props.name
that references the value jsxRocks
.
Passing functions as callback is also common practice when writing JSX components. A basic example would look like:
<AwesomeComponent
handleNameChange={data => myAction(data)}
/>
Whoah, let's not a couple of things here:
{}
. Where did that come from?
JSX can take JavaScript expressions as arguments to props. This
means that you're not restricted to string props. You can pas
functions to children that make handling callback easier.
To extend the example, this means we can use any logic we want inside of component's attributes. Need computed data at render time? Not problem
<AwesomeComponent
conditionalProp={thing === true ? 'thisprop' : 'thatprop'}
/>
Keep in mind that when creating functions inside of components
render
method (like we're doing with the expressions in props), that
a new function is created on each re-render.
This is a pretty minor thing for most apps, but as the size of application grows and you start thinking about performance, minimizing the amount of work on the client can be idea.
If we take our two examples from above, they would be better written so a new function is not created and the class intsance can take care of re-computing the value:
class AwesomeComponent extends React.Component {
conditionalProp() {
return this.props.thing ? 'prop1' : 'prop2'
}
render() {
const { thing } = this.props
return (
<AwesomeComponent
conditionalProp={this.conditionalProp()}
/>
)
}
}
When the render
method of a component is called, functions inside of
the JSX are executed and their return values are used in place of the
props. That brings up two common use-cases for using expression in
components:
Using a reference to a function
Sometimes you will need to provide a callback method to child component - and sometimes you will need to provide the first argument to a function and let the child provide the rest. In those cases, anonymouse functions work perfectly:
<AwesomeComponent
conditionalProp={data => myCallback(id, data)}
/>
What we're doing in the above example is called partial function
application. In a nutshell, we create a unary
function that returns
a binary
function with the first argument already given (so really,
we get a unary
function again).
When the render
method of the component is called, functions are
executed. With the example above again, what we actually get after
the render is:
<AwesomeComponent
handleCallback={data => myCallback(id, data)}
/>
And inside of AwesomeComponent
, you can simply call:
this.props.handleCallback(arg)
Using the value of a function
class AwesomeComponent extends React.Component {
conditionalProp() {
return this.props.thing ? 'prop1' : 'prop2'
}
render() {
const { thing } = this.props
return (
<AwesomeComponent
conditionalProp={this.conditionalProp()}
/>
)
}
}
Passing boolean properties to JSX components is simple. The only thing you need to know is that they are JavaScript Booleans, not String Booleans. In other words:
This is correct:
<AwesomeComponent
handleCallback={true}
/>
This is not:
<AwesomeComponent
handleCallback="true"
/>
Just a quick note that the second one actually is valid, but it's
not considered a boolean
it's considered a string
.
An alternative for passing true
is to simply provide the prop name without a value:
<Input disabled/>
My professional opinion is to always use the full true
or false
value for the sake of readability.
Are there any pieces of JSX where you got caught up first starting? Let's chat - shoot me a message on twitter @CodyReichert and I'll add it!
:: Cody Reichert