JSX (JavaScript XML) is a syntax for embedding XML directly into JavaScript code.
This allows for some neat new logical paths, such as returning a block of HTML code to the caller of a JavaScript function.
Here is an example of a component written without JSX - notice that e()
is a shorthand for React.createElement()
:
react-nojsx.index.html
<!-- Load Bootstrap CSS from CDN --> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- Load React from CDN --> <!-- Note: when deploying to production, replace "development.js" with "production.min.js". --> <script src="//unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="//unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> <div id="react_test">Component failed to load</div> <script> 'use strict'; var e = window.React.createElement; var ReactDOM = window.ReactDOM; class MetadataTable extends React.Component { constructor(props) { super(props); this.state = { headers: [ { key: 'name', label: 'Name' }, { key: 'type', label: 'Type' }, { key: 'lastUpdated', label: 'Last Updated' }, { key: 'value', label: 'Value' }, { key: 'additionalActions', label: 'More...' } ], data: [ { 'name': 0, 'value': 'hello'}, { 'name': 1, 'value': 'react'}, { 'name': 2, 'value': 'without'}, { 'name': 3, 'value': 'jsx'}, ] }; } getTableHeaders() { var tableHeaders = []; for(var i = 0; i < this.state.headers.length; i++) { var header = this.state.headers[i]; var uniqueKey = 'table_header_' + header.key; // Push table header cells into the header row tableHeaders.push(e('th', { 'key': uniqueKey, 'width': `${100 / this.state.headers.length}%` }, `${header.label}`)); } // Accumulate and return table header elements return tableHeaders; } getTableRowData() { var tableRows = []; for(var i = 0; i < this.state.data.length; i++) { var item = this.state.data[i]; var uniqueKey = 'table_row_data_' + i.toString(); var rowData = []; // Loop over selected headers to print table row values for(var j = 0; j < this.state.headers.length; j++) { var header = this.state.headers[j]; var uniqueKey = 'table_' + header.key.toString() + '_' + i.toString(); // Push table cell values into a "row" // NOTE: sketchy hack at the end to coerce to a String rowData.push(e('td', { 'key': uniqueKey, 'width': `${100 / this.state.headers.length}%`}, `${item[header.key]}`)); } // Push rows of cells into the table tableRows.push(e('tr', { 'key': uniqueKey }, rowData)); } // Accumulate and return table row elements return tableRows; } handleNewValueChange(event) { console.debug("OnChange Event:", event); this.setState({ 'newValue': event.target.value }); } addNew(event) { console.debug("OnClick Event:", event); let data = this.state.data; data.push({ 'name': this.state.data.length, 'value': this.state.newValue }); this.setState({ 'data': data }); this.setState({ 'newValue': '' }); } render() { // Re-fetch selected headers and row data var tableHeaders = this.getTableHeaders(); var tableRows = this.getTableRowData(); // Append an additional row with a submit button to the form tableRows.push(e('tr', { 'key': 'submitBtn' }, e('td', {}, e('input', { 'placeholder': 'Dummy text input...', 'value': this.state.newValue, onChange: (event) => this.handleNewValueChange(event) }) ), e('td', {}, e('button', { 'className': 'btn btn-xs btn-primary', onClick: (event) => this.addNew(event) }, 'Add new') ) )); // Render the table data with React return e('div', { 'className': 'table-responsive' }, e('table', { 'className': 'table table-condensed table-hover'}, e('thead', {}, e('tr', { 'key': 'headers' }, tableHeaders)), e('tbody', {}, tableRows)) ); } } console.log("Rendering!"); var domContainer = document.querySelector('#react_test'); ReactDOM.render(e(MetadataTable), domContainer); console.log("Rendered!"); </script>
With JSX
Now, here is the same component converted to use JSX syntax.
Notice that we are no longer passing around the values returned from React.createElement
... in fact, we don't even call explicitly call React.createElement
at all: