You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

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:



  • No labels