Getting Started with React (6) Deep into JSX
The main content of this blog is in-depth JSX-related content from the Advanced Guidelines section of the React doc.
What is JSX?
In fact, JSX is just syntactic sugar for the’React.createElement (component, props,… children) 'function. The following JSX code:
1 | <MyButton color="blue" shadowSize={2}> |
Will compile as:
1 | React.createElement( |
If there is no sub-node, you can also use self-closing tag forms, such as:
1 | <div className="sidebar" /> |
Will compile as:
1 | React.createElement( |
That is to say, in fact, the so-called JSX needs to be compiled to generate React code, which is somewhat similar to Vue’s template. Vue’s template will also be compiled to generate a render function. In this function, for each tag, it will call its own API to create vnode.
Specify
The first part of the JSX tag specifies the type of the React element.
JSX tags that start with a capital letter mean they are React components. These tags are compiled as direct references to named variables, so when you use JSX < Foo/> expressions, ‘Foo’ must be included in scope.
React
Since JSX compiles as React.createElement calls, the React library must also be included in the JSX code scope.
For example, in the following code, although’React ‘and’CustomButton’ are not directly used, they still need to be imported:
1 | import React from 'react';import CustomButton from './CustomButton'; |
If you load React directly through the < script > tag instead of using a JavaScript packaging tool, you must mount React into a global variable.
In
In JSX, you can also use dot syntax to reference a React component. This is very handy when you export many React components in a module. For example, if’MyComponents. DatePicker 'is a component, you can use it directly in JSX:
1 | import React from 'react'; |
User-defined components must start with a capital letter
Elements starting with a lowercase letter represent an HTML built-in component, such as’ < div > ‘or’ < span > ‘will generate the corresponding string “div” or “span” to be passed to’React.createElement’ (as a parameter). Elements starting with uppercase letters correspond to components introduced or customized in JavaScript, such as’ < Foo/> 'will compile to’React.createElement (Foo) '.
We recommend naming custom components with uppercase letters. If you do need a component that starts with a lowercase letter, you must assign it to a variable that starts with an uppercase letter before using it in JSX.
For example, the following code will not run as expected.
1 | import React from 'react'; |
To fix this, we need to rename hello to Hello and use < Hello/> in JSX:
1 | import React from 'react'; |
Select type at runtime
You cannot use a universal expression as a React element type. If you want to (dynamically) determine the element type through a universal expression, you need to first assign it to a variable starting with a capital letter. This is usually used when rendering different components based on prop:
1 | import React from 'react'; |
To solve this problem, we need to first assign the type to a variable starting with a capital letter.
1 | import React from 'react'; |
JSX
There are several ways to specify props in JSX.
JavaScript
You can pass a JavaScript expression wrapped in ‘{}’ as a prop to a JSX element. For example, JSX like this:
1 | <MyComponent foo={1 + 2 + 3 + 4} /> |
In MyComponent, the value of props.foo is equal to the result of 1 + 2 + 3 + 4.
'If ‘statements and’for’ loops are not JavaScript expressions, so they cannot be used directly in JSX. However, you can use them in code other than JSX. For example:
1 | function NumberDescriber(props) { |
You can learn more about it in the corresponding chapters条件渲染And循环The content.
String literal
You can assign string literals to prop. The following two JSX expressions are equivalent:
1 | <MyComponent message="hello world" /> |
When you assign a string literal to a prop, its value is unescaped. Therefore, the following two JSX expressions are equivalent:
1 | <MyComponent message="<3" /> |
This behavior is usually unimportant, here is just a reminder of this usage.
Props
If you do not assign a value to prop, its default value is’true '. The following two JSX expressions are equivalent:
1 | <MyTextBox autocomplete /> |
Generally, we do not recommend not passing value to prop, as this may be related to ES6 对象简写Confused, ‘{foo}’ is short for ‘{foo: foo}’, not ‘{foo: true}’. This implementation is only to maintain the same behavior as tag attributes in HTML.
Attribute expansion
If you already have a props object, you can use the expansion operator… to pass the entire props object in JSX. The following two components are equivalent:
1 | function App1() { |
You can also choose to keep only the props that the current component needs to receive, and use the expansion operator to pass other props down.
1 | const Button = props => { |
In the above example, the prop of’kind ‘will be safely kept and will * not * be passed to the’ < button > ‘element in the DOM. All other props will be passed through the’… other ‘object, making the application of this component very flexible. You can see that it passes an’onClick’ and’children 'attribute.
Attribute expansion is useful in some cases, but it is also easy to pass unnecessary props to unrelated components or invalid HTML attributes to the DOM. We recommend using this syntax with caution.
JSX
The content of the JSX expression contained between the start and end tags will be passed to the outer component as a specific attribute’props.children '. There are several different ways to pass child elements:
String literal
You can put the string between the start and end tags, where’props.children 'is just the string. This is useful for many built-in HTML elements. For example:
1 | <MyComponent>Hello world!</MyComponent> |
This is a valid JSX, and the props.children in MyComponent is a simple non-Escape Character string “Hello world!”. So you can write JSX the same way you write HTML. As shown below:
1 | <div>This is valid HTML & JSX at the same time.</div> |
JSX will remove spaces at the beginning and end of the line as well as blank lines. Empty lines adjacent to the label will be deleted, and new lines between text strings will be compressed into one space. Therefore, the following methods are equivalent:
1 | <div>Hello World</div> |
JSX
Child elements can be composed of multiple JSX elements. This is very useful for nested components.
1 | <MyContainer> |
You can mix different types of child elements together, so you can use string literals with JSX child elements. This is also a manifestation of JSX similar to HTML, so the following code is legal JSX and also legal HTML:
1 | <div> |
React components can also return a set of elements stored in an array:
1 | render() { |
JavaScript
JavaScript expressions can be wrapped in ‘{}’ as child elements. For example, the following expressions are equivalent:
1 | <MyComponent>foo</MyComponent> |
This is very useful for displaying lists of arbitrary length. For example, rendering HTML lists:
1 | function Item(props) { |
JavaScript expressions can also be combined with other types of child elements. This approach can conveniently replace template strings.
1 | function Hello(props) { |
Function as a child element
Usually, JavaScript expressions in JSX will be evaluated as strings, React elements, or lists. However, ‘props.children’, like other props, can pass any type of data, not just the renderable types known to React. For example, if you have a custom component, you can pass the callback function as’props.children ':
1 | //Call the child element callback numTimes times to repeatedly generate the component |
You can pass anything as a child element to a custom component, just make sure it can be converted into an object that React understands before rendering it. This usage is not common, but can be used to extend JSX.
Boolean type, Null
'False ‘,’ null ‘,’ undefined ‘, and’true’ are valid child elements. But they will not be rendered. The following JSX expressions render the same:
1 | <div /> |
This helps to render other React elements based on specific conditions. For example, in the following JSX, the < Header/> component is rendered only when’showHeader ‘is’true’:
1 | <div> |
It is worth noting that there are some “falsy” 值, like the number ‘0’, will still be rendered by React. For example, the following code will not work as you expect, because ‘0’ will still be rendered when’props.messages’ is an empty array:
1 | <div> |
To solve this problem, make sure that the expression before ‘& &’ is always a boolean value:
1 | <div> |
Conversely, if you want to render values such as’false ‘,’ true ‘,’ null ‘,’ undefined ', you need to first convert them转换为字符串:
1 | <div> |
Summary
There is nothing to understand in this section, it is all grammatical issues, but there are a few places to pay attention to:
- React components must be in scope.
- Names of React components must start with uppercase.
- The content between component tags will be as prop.children, which can be expressions, functions, strings, etc.
- It’s worth noting that there are some “falsy” 值, such as the number ‘0’, will still be rendered by React. For example, the following code will not work as you expect, because ‘0’ will still be rendered when’props.messages’ is an empty array: To solve this problem, make sure that the expression before ‘& &’ is always a boolean value: