0.1.0 • Published 2 years ago

babel-plugin-jsx-on-demand-children v0.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

Build Status Babel Macro Code Coverage version downloads MIT License

PRs Welcome Code of Conduct

Introduction

A React component added to the tree will always evaluate all of its properties including the component body. A simple example of this (taken from jsx-control-statements) is attempting to implement a conditional component:

<IfComponent condition={item}>
  <Text>{item.title}</Text>
</IfComponent>

The error will be "Cannot read property 'title' of undefined", because React will evaluate the body of the custom component and pass it as "children" property to it. The only workaround is to force React into lazy evaluation by wrapping the statement in a function.

<IfComponent condition={item} render={() => (<Text>{item.title}</Text>)}></IfComponent>

This is precisely what this plugin/macro does, albeit with a slightly different syntax:

<AsyncHandler status={status}>
  <JsxOnDemandChildren>
    <AsyncHandler.Loading>...</AsyncHandler.Loading>
    <AsyncHandler.Success>...</AsyncHandler.Success>
    <AsyncHandler.Error>...</AsyncHandler.Error>
  </JsxOnDemandChildren>
</AsyncHandler>

becomes:

<AsyncHandler 
  Loading={() => <AsyncHandler.Loading>...</AsyncHandler.Loading>} 
  Success={() => <AsyncHandler.Success>...</AsyncHandler.Success>}
  Error={() => <AsyncHandler.Error>...</AsyncHandler.Error>}>
</AsyncHandler>

This is most useful for components written to take advantage of this plugin, in the example above the AsyncHandler component could look like this:

function AsyncHandler({status, Loading, Success, Error}) {
  return (
    {status === 'loading' && <Loading/>}
    {status === 'success' && <Success/>}
    {status === 'error' && <Error/>}
  );
}

Installation

Option 1: As a macro (Recommended)

Install babel-plugin-macros and babel-plugin-jsx-on-demand-children to your devDependencies:

npm install --save-dev babel-plugin-macros babel-plugin-jsx-on-demand-children

Add babel-plugin-macros to your babel configuration:

Adding babel-plugin-macros to your config

Usage

If installed as a macro, import it

import JsxOnDemandChildren from 'babel-plugin-jsx-on-demand-children/macro'

// or
const JsxOnDemandChildren = require('babel-plugin-jsx-on-demand-children/macro')

Create your custom component, ie:

export default function Conditional({ condition, If, Else}) {
  return condition ? (<If />) : (<Else />);
}

Conditional.If = function({children}) {
  return <>{children}</>;
}

Conditional.Else = function({children}) {
  return <>{children}</>;
}

Use with <JsxOnDemandChildren>:

import Conditional from './Conditional';

function SomeComponet() {
  return (
    <Conditional condition={isOk}>
      <JsxOnDemandChildren>
        <Conditional.If>
          Everything is fine!
        </Conditional.If>
        <Conditional.Else>
          We have a problem!
        </Conditional.Else>
      </JsxOnDemandChildren>
    </Conditional>
  );
}

LICENSE

MIT