repetere / jsonx

JSONX - Create React Elements, JSX and HTML from JSON
https://repetere.github.io/jsonx/
MIT License
171 stars 17 forks source link

componentLibraries vs reactComponents #7

Closed craigcoles closed 6 years ago

craigcoles commented 6 years ago

What is the difference between surrounding componentLibraries and reactComponents? In my application, the naming conventions range from:

<Button/>
<Layout.Full/>
<Layout.Center/>
<Select/>
<Select.Item/>
<Menu/>

These are all my own custom components.

yawetse commented 6 years ago

I haven't looked at this in awhile but, i believe the main difference is a component Library is an object with multiple components (like Semantic UI) - https://github.com/repetere/rjx#advanced---using-custom-components--ui-libraries

const Semantic = {
  Component1,
  Component2,
}

I believe those subcomponents can be nested Component.SubComponent

In your case, I think you want to use reactComponents, where you pass an object with all of the custom components you want to use: https://github.com/repetere/rjx#advanced---using-new--custom-components

The only issues I see is Layout.Full would not be a valid object property name, so you may effectively have a "library" called "Layout" and in RJX you could reference your components as "Layout.Full"

craigcoles commented 6 years ago

I did think ReactComponents would be the correct one for my use case, but it kept complaining aboutLayout.Full.

Example

Helpers/RJX.js

import * as RJX from 'rjx/src/main';
import Components from "Components";

const getRenderedJSON = RJX.getRenderedJSON.bind({
  reactComponents: {
    Components
  }
});

export default getRenderedJSON;

Scenes/Test.js

import React, { Component } from "react";
import getRenderedJSON from 'Helpers/RJX';

const data = {
  "component": "Layout.Full",
  "children": [
    {
      "component": "Text",
      "children": "Hello World!"
    }
  ]
}

export default class Test extends Component {
  render() {
    return getRenderedJSON(data)
  }
}

Result

yawetse commented 6 years ago

@craigcoles another option (depending on how complicated your Layout components are) because you can define the components completely in JSON if you want https://github.com/repetere/rjx#advanced---custom-react-components--lifecycle-functions

yawetse commented 6 years ago

can you show me what's exported from import Components from "Components";?

//if Components === Layout, e.g {Full:some react component, Half:some react component}

then use component library
yawetse commented 6 years ago

try this:

Helpers/RJX.js

import * as RJX from 'rjx/src/main';
import {Components as Layout} from "Components";

const getRenderedJSON = RJX.getRenderedJSON.bind({
  reactComponents: {
    Layout,
  }
});

export default getRenderedJSON;
craigcoles commented 6 years ago

In terms of the Layout component, its just a combination of small components as shown:

Components/Layout/index.js

function Center(props: Props): React$Element<any> {
  ...
}

function Full(props: Props): React$Element<any> {
  ...
}

function Padded(props: Props): React$Element<any> {
  ...
}

const Layout = {
  Center,
  Full,
  Padded
};

export default Layout;

Components/index.js

import Button from 'Components/Button';
import Layout from 'Components/Layout';
import Select from 'Components/Select';
import Menu from 'Components/Menu';

export default {
  Button,
  Layout,
  Select,
  Menu
};
yawetse commented 6 years ago

do your other components work (like Button, Select and Menu)?

craigcoles commented 6 years ago

They do not 🤔 This is what I have just tested:

const data = {
  "component": "Text",
  "children": "Hello World!"
}

I do have a Text component that I haven't mentioned about 😅

yawetse commented 6 years ago

So by default the only available components come from ReactDOM, so 'div' or 'textarea' etc so component:"Text" won't work because it's not defined

yawetse commented 6 years ago

also for your components, you want to use a component library

yawetse commented 6 years ago

this is a good example: https://github.com/repetere/rjx/blob/master/test/unit/components_spec.js#L137

import * as RJX from 'rjx/src/main';
import Components from "Components";

const componentLibraries = {
      Components,
    };

const getRenderedJSON = RJX.getRenderedJSON.bind({
 componentLibraries,
});

export default getRenderedJSON;
yawetse commented 6 years ago

Then you would reference it like this:

import React, { Component } from "react";
import getRenderedJSON from 'Helpers/RJX';

const data = {
  "component": "Components.Layout.Full",
  "children": [
    {
      "component": "Text",
      "children": "Hello World!"
    }
  ]
}

export default class Test extends Component {
  render() {
    return getRenderedJSON(data)
  }
}
craigcoles commented 6 years ago

@yawetse Massive thanks! I have it working using your example!