Wednesday, May 30, 2018

React readability

Let's say you have this view model controlled by Redux reducer. Its view (React.ComponentClass) property is code-splitted by webpack, so the view is dynamically loaded (e.g., from nested routing by redux-first-router's thunk). Which would require the view be nullable.

export interface IJobFormViewModel
{
    view: React.ComponentClass | null;
    model: IJobFormModel;
}

export interface IJobFormModel
{
    jobId?: number | 'new';

    // lookups
    states: IStateCityDto[];
    durationTypes: IDurationTypeDto[];
    locationTypes: ILocationTypeDto[];

    // form's initial values
    initialValues?: IJobDto;
}

There are three ways the parent component can render the nested component.

Option 1:
const {jobId} = this.props.rootState.jobForm.model;

const JobFormView =
    this.props.rootState.jobForm.view ?
        <this.props.rootState.jobForm.view/>
        :
        <></>;

return <>
    <Helmet>
        <title>My Job Posts</title>
    </Helmet>

    <ReactTable
       ...
    />


    {jobId && JobFormView}

</>;

That's ok, but it's not readily obvious that the JobFormView is a component, it could just be a number, string or date only.


Option 2:
const {jobId} = this.props.rootState.jobForm.model;

const JobFormView = this.props.rootState.jobForm.view || 'span';

return <>
    <Helmet>
        <title>My Job Posts</title>
    </Helmet>

    <ReactTable
       ...
    />


    {jobId && <JobFormView/>}

</>;


Looks good, however the span tag would be included in page's markup whenever the nested view is not yet loaded.

You might be tempted to use this, but this won't work.
const JobFormView = this.props.rootState.jobForm.view || 'React.Fragment';


<React.Fragment> tag is a compiler magic, it will not appear on page's markup. However the following, not only it is a compiler error

const BeeAre = 'br';
const RF = 'React.Fragment';

return <>
    Hello
    <BeeAre/>
    <RF/>
    World
</>;





It would also cause error on browser




Besides 'React.Fragment' is a magic string, yet it does not do any magic, it just makes the markup invalid.

Option 3
const {jobId} = this.props.rootState.jobForm.model;

const JobFormView = this.props.rootState.jobForm.view;

return <>
    <Helmet>
        <title>My Job Posts</title>
    </Helmet>

    <ReactTable
       ...
    />


    {jobId && JobFormView && <JobFormView/>}

</>;


That's the perfect option, not only that the component is obvious, there are no extraneous markup (e.g., span) that would appear on page when the nested view is not yet loaded.

No comments:

Post a Comment