React Design Patterns and Best Practices(Second Edition)
上QQ阅读APP看书,第一时间看更新

Control statements

Conditionals and loops are very common operations in UI templates, and you may feel wrong using the JavaScript ternary or the map function to perform them. JSX has been built in such a way that it only abstracts the creation of the elements, leaving the logic parts to real JavaScript, which is great except that, sometimes, the code becomes less clear.

In general, we aim to remove all the logic from our components, and especially from our render methods, but sometimes we have to show and hide elements according to the state of the application, and very often we have to loop through collections and arrays.

If you feel that using JSX for that kind of operation will make your code more readable, there is a Babel plugin available to do just that: jsx-control-statements.

This follows the same philosophy as JSX, and it does not add any real functionality to the language; it is just syntactic sugar that gets compiled into JavaScript.

Let's see how it works.

First of all, we have to install it:

  npm install --save jsx-control-statements

Once it is installed, we have to add it to the list of our babel plugins in our .babelrc file:

  "plugins": ["jsx-control-statements"]

From now on we can use the syntax provided by the plugin and Babel will transpile it together with the common JSX syntax.

A conditional statement written using the plugin looks like the following snippet:

  <If condition={this.canShowSecretData}> 
<SecretData />
</If>

This gets transpiled into a ternary expression as follows:

  {canShowSecretData ? <SecretData /> : null}

The If component is great, but if, for some reason, you have nested conditions in your render method, it can easily become messy and hard to follow. Here is where the Choose component comes in handy:

  <Choose> 
<When condition={...}>
<span>if</span>
</When>
<When condition={...}>
<span>else if</span>
</When>
<Otherwise>
<span>else</span>
</Otherwise>
</Choose>

Please note that the preceding code gets transpiled into multiple ternaries.

Finally, there is a component (always remember that we are not talking about real components but just syntactic sugar) to manage the loops that are also very convenient:

  <ul> 
<For each="user" of={this.props.users}>
<li>{user.name}</li>
</For>
</ul>

The preceding code gets transpiled into a map function – no magic there.

If you are used to using linters, you might wonder why the linter is not complaining about that code. The user variable does not exist before the transpilation, nor is it wrapped into a function. To avoid those linting errors, there is another plugin to install: eslint-plugin-jsx-control-statements.

If you did not understand the previous sentence, don't worry; we will talk about linting in the following section.