Skip to main content

React Generator

Iteria Low-code allows you to generate React code from templates and edit generated code.

When generating a page, you can choose whether you want to Generate React in Generate Page window. By selecting this option, the page generation will create the React code for each selected page based on templates.

React code generation will be supported for:

  • list of entities (datagird)
  • detail of an entity (form)

The react generator uses two key features: Renaming and React inlining.

Renaming

A one of the key features of the React code generation is the renaming of keywords and fields from the GraphQL schema when adding new columns in the datagrid or inputs in the form. Clone element supports this form of renaming.

Renaming finds occurrences of template's keywords or the entity's fields, which are then replaced with the new selected field.

React Inlining

Iteria Low-code uses React component inlining during code generation to replace custom React component call with its implementation.

React inlining substitutes all occurrences of a desired React component with its implementation, adding the necessary imports to the source code, the component body, and then the component itself is replaced in the source code with its return value. When substituting a component call, the attributes in the implementation are replaced with attributes of the called component.

After modification original component imports are removed and in the resulting source code string literals are flatten.

String literals flatten

String literals flatten replaces all unnecessary literals and binary expressions e.g.:

  • `${'customers'}` to 'customers'
  • date_of_birth ? 'customers.date_of_birth' : 'customers' to 'customers.date_of_birth'

Example

In the following example there are 2 React components: Translate and DateFormat, which are substitued by their implementation during React inlining.

The result is in the Modified code section.

Original code

Translate and DateFormat contain atributes, which we want to substitute in the resulting code.

import React from 'react'
import { DataGrid, GridCellParams, GridColDef } from '@mui/x-data-grid'
import Translate from '../../i18n/Translate'
import DateFormat from '../readonly/DateFormat'
import { useIntl } from 'react-intl'

interface Props {
data: any
loading: boolean
}

const CustomersListView: React.FC<Props> = (props: Props) => {
const columns: GridColDef[] = [
{
field: 'customers.date_of_birth',
renderHeader: () => (
<Translate
entityName='customers'
fieldName='date_of_birth'
defaultMessage='Date of birth'
/>
),
width: 150,
renderCell: (params: GridCellParams) => <DateFormat values={params} />,
},
]

return (
<DataGrid
rows={props?.data?.customers ?? []}
columns={columns}
loading={props?.loading}
/>
)
}

export default CustomersListView

Translate.tsx

Implementation of the Translate component.

import React from 'react'
import { FormattedMessage } from 'react-intl'

interface TranslateProps {
entityName: string
fieldName?: string
defaultMessage?: string
}

const Translate: React.FC<TranslateProps> = ({
entityName,
fieldName,
defaultMessage,
}) => {

return (
<FormattedMessage
tagName={({ children }: any) => (
<span
className="translate"
dangerouslySetInnerHTML={{ __html: children }}
data-message-id={
fieldName ? `${entityName}.${fieldName}` : `${entityName}`
}
/>
)}
id={fieldName ? `${entityName}.${fieldName}` : `${entityName}`}
defaultMessage={
defaultMessage ??
(fieldName ? `${fieldName} (${entityName})` : entityName)
}
/>
)
}

export default Translate

DateFormat.tsx

Implementation of the DateFormat component.

import { useIntl } from "react-intl"

export const DateFormat = ({ value }) => {
const intl = useIntl()
return value.row.date_of_birth ? intl.formatDate(value.row.date_of_birth) : ''
}

Modified code

The resulting code in which Translate and DateFormat are substituted, string literals are flatten and original components import are removed.

import React from 'react'
import { DataGrid, GridCellParams, GridColDef } from '@mui/x-data-grid'
import { FormattedMessage } from 'react-intl'
import { useIntl } from 'react-intl'

interface Props {
data: any
loading: boolean
}

const CustomersListView: React.FC<Props> = (props: Props) => {
const intl = useIntl()

const columns: GridColDef[] = [
{
field: 'customers.date_of_birth',
renderHeader: () => (
<FormattedMessage
tagName={({ children }: any) => (
<span
className="translate"
dangerouslySetInnerHTML={{ __html: children }}
data-message-id="customers.date_of_birth"
/>
)}
id="customers.date_of_birth"
defaultMessage="Date of birth"
/>
),
width: 150,
renderCell: (params: GridCellParams) =>
params.row.date_of_birth
? intl.formatDate(params.row.date_of_birth)
: '',
},
]

return (
<DataGrid
rows={props?.data?.customers ?? []}
columns={columns}
loading={props?.loading}
/>
)
}

export default CustomersListView

Import manipulation

Generator uses multiple templates (which are small individual applications) that are to be used in one target application therefore AST import manipulation is needed:

  • @namespace/common - indexed imports from common template only for types and running only template will be removed in generation

  • @namespace/common/path/to/component - imports with full path from common template will be changed in generation to relative