React JSON Syntax (RJX)
Description
React JSON Syntax (RJX) takes a RXJ JSON object and can create (Suspense, Lazy, Functional and Class) React Components, output HTML and JSX and render React components without transpilers. RJX lets you get up and running with React without extra configuration management of more complicated tool chains.
Installation
$ npm i rjx
Full Documentation
HTML/Browser Example )
Examples (;const exampleRJX = component:'p' props:style:color:'blue' children:'hello world';//Rendering React Componentsrjx;// => JSX Equivalent: <p style={{color:'blue'}}>hello world</p> const exampleToHTMLandJSX = component: 'div' props: className:'rjx-generated' children: component:'p' props: style: color:'red' children:'hello world' ;//Generating HTML stringsrjx;// => '<div class="rjx-generated"><p style="color:red;">hello world</p></div>'//Generating JSX stringsrjx;// => '<div class="rjx-generated"><p style={{color:red,}}>hello world</p></div>' //Rendering HTML Dom with Reactrjx;// <!DOCTYPE html>// <body>// <div id="myApp">// <div class="rjx-generated">// <p style="color:red;">hello world</p>// </div>// </div>// </body>
RJX JSON Spec
RXJ JSON is valid JSON that more or less mimics JSX in JSON notation with a couple of special properties. The properties for RXJ JSON are the arguments passed to React.createElement. The only required property is the component (which is passed as the type
argument)
React
You can pass React component libraries for additional components, or you own custom components (see Advanced, also see Full Spec).
//sample RJX component:'ul' props: className:'list-class' children: component:'li' children:'first bullet' component:'li' children:'second bullet'
// Equivalent JSX<ul className="list-class"> <li>first bullet</li> <li>second bullet</li></ul>
Validating RJX JSON
; //use the built in RJX Validatorconst valid_rjx_json = component:'p' props: className:'title' children:'hello world';const invalid_rjx_json = props: className:'title' children:'hello world';const multiple_invalid_rjx_json = props:'must be obj' children:'hello world'; rjx_rjxUtils // => truerjx_rjxUtils // => throws SyntaxError('[0001] Missing React Component')rjx_rjxUtils // =>// [ [Error: [0001] Missing React Component],[ Error: [0002] props must be an Object / valid React props] ] /** * @param * @param * /function validateRJX(rjx = {}, returnAllErrors= false);
Simple RJX Syntax
If you want to save time, you can use the property name as the component and define properties for a cleaner simple syntax
//shorthand simple rjx ul: props: className:'list-class' children: li: children:'first bullet' li: children:'second bullet'
RJX Module
"rjx" : getReactElement: Function: getReactElement aliases:getRenderedJSONgetReactElementFromRJX //Use React.createElement and RJX JSON to create React elements getReactElementFromJSON: Function: getReactElementFromJSON // Use compiledJSON object {type,props,children} to create React elements rjxRender: Function: getRenderedJSON //Use RJX without any configuration to render RJX JSON to HTML and insert RJX into querySelector using ReactDOM.render outputHTML: Function: outputHTML //Use ReactDOMServer.renderToString to render html from RJX outputJSX: Function: outputJSX //Generate valid JSX from RJX outputJSON: Function: outputJSON //Generate computed static values from RJX into JSON compile: Function: compile //Generate React Function Component from RJX jsonToJSX: Function: jsonToJSX //Converts JSON to JSX __express: Function: __express //render express views with RJX __getReact: Function: __getReact //Expose reference to React __getReactDOM: Function: __getReactDOM //Expose reference to ReactDOM __getUseGlobalHook: Function: __getUseGlobalHook //Expose reference to useGlobalHook _rjxChildren: getChildrenProperty: Function: getChildrenProperty // returns a valid rjx.children property getChildrenProps: Function: getChildrenProps // Used to pass properties down to child components if passprops is set to true getRJXChildren: Function: getRJXChildren // returns React Child Elements via RJX _rjxComponents: componentMap: {} // object of all react components available for RJX getBoundedComponents: Function: getBoundedComponents // getBoundedComponents returns reactComponents with certain elements that have this bounded to select components in the boundedComponents list getComponentFromLibrary: Function: getComponentFromLibrary // returns a react component from a component library (like material-ui, or semantic-ui) getComponentFromMap: Function: getComponentFromMap // returns a react element from rjx.component getReactClassComponent: Function: getReactClassComponent // returns a react class component and support lifecycle functions, lazy and suspense components getReactFunctionComponent: Function: getReactFunctionComponent // returns a react function component and support lifecycle functions, hooks, lazy and suspense components _rjxProps: getRJXProps: Function: getRJXProps // It uses traverse on a traverseObject to returns a resolved object on propName. So if you're making an ajax call and want to pass properties into a component, you can assign them using asyncprops and reference object properties by an array of property paths getEvalProps: Function: getEvalProps //Used to evalute javascript and set those variables as props. getEvalProps evaluates __dangerouslyEvalProps and __dangerouslyBindEvalProps properties with eval, this is used when component properties are functions, __dangerouslyBindEvalProps is used when those functions require that this is bound to the function. For __dangerouslyBindEvalProps it must resolve an expression, so functions should be wrapped in (). I.e. (function f(x){ return this.minimum+x;}) getComponentProps: Function: getComponentProps // Resolves rjx.__dangerouslyInsertComponents into an object that turns each value into a React components. This is typically used in a library like Recharts where you pass custom components for chart ticks or plot points. getReactComponentProps: Function: getReactComponentProps // Resolves rjx.__dangerouslyInsertReactComponents into an object that turns each value into a the React component from reactComponents, componentLibraries or ReactDOM. getFunctionFromProps: Function: getFunctionFromProps // Takes a function string and returns a function on either this.props or window. getFunctionProps: Function: getFunctionProps // Returns a resolved object from function strings that has functions pulled from rjx.__functionProps getWindowComponents: Function: getWindowComponents // Returns a resolved object that has React Components pulled from window.__rjx_custom_elements getComputedProps: Function: getComputedProps // Returns computed properties for React Components and any property that's prefixed with __ is a computedProperty _rjxUtils: validateRJX: Function: validateRJX //Validates RJX JSON Syntax displayComponent: Function displayComponent // Used to evaluate whether or not to render a component traverse: Function traverse //take an object of array paths to traverse and resolve getAdvancedBinding: Function: getAdvancedBinding // Use to test if can bind components this context for react-redux-router
Full RJX Spec
rjx = //standard properties component:String // Any React DOM element, or custom component div,p, Boomer.Hero, MaterialUI.Button, myCustomComponent (can also use the property 'type' instead of 'component') props:Object // Standard React component properties children:Array|String // Any String or Array of valid RJX JSON objects //dynamic properties resourceprops:Object // An object from async resources to merge onto rjx.props once fully resolved asyncprops:Object // An object from async resources to merge onto rjx.props once fully resolved (alias for resourceprops) thisprops:Object // An object to merge onto rjx.props from properties already bound to this.props windowprops:Object // An object to merge onto rjx.props from the window object //evaluated properties __dangerouslyEvalProps:Object // An object of evaluated JavaScript strings, used as inline functions onto rjx.props, if the prop is a function it will be called bound to 'this' and the returned value will be assigned __dangerouslyBindEvalProps:Object // An object of evaluated JavaScript functions that are bound to this, used as inline functions onto rjx.props //computed properties __functionProps:Object // An object of parsed function strings(func:this.props.onClick, func:window.localStorage.getItem),merged onto rjx.props __dangerouslyInsertComponents:Object // An object that turns each RXJ JSON value into a React components. This is typically used in a library like Recharts where you pass custom components for chart ticks or plot points. __dangerouslyInsertReactComponents:Object // An object that returns the react element from either ReactDOM, reactComponents or componentLibraries. __spreadComponent:Object // A RJX element that is mapped on any array prop called __spread __windowComponents:Object // An object of components merged onto rjx.props from window.__rjx_custom_elements __windowComponentProps:Object //display properties comparisonprops:Object // An array of Objects used to conditionally display the current rjx.component //flag properties passprops:Boolean // A flag to pass parent properties to children RJX objects (except for the style property) comparisonorprops:Boolean // A flag to use an or condition instead of and conditions between comparisions
Advanced - Using Custom Components & UI Libraries
If you plan on using an entire UI library, then bind the library to this before using RJX.
;; const getReactElement = rjxgetReactElement; const myRJX = component:'Semantic.Container' children: component:'Semantic.Header' props: as:'h1' children:'Hello World!' component:'Semantic.Button' props: content:'Discover docs' href:'http://react.semantic-ui.com' icon:'github' labelPosition:'left' const myReactElements = ;
Advanced - Using New & Custom Components
If you're only adding single components or using your own components you can add them to RJX's component my individually.
;;; Component { return <a ...thisprops>thispropschildren</a> } const getReactElement = rjxgetReactElement; const myRJX = component:'div' children: component:'Header' props: as:'h1' children:'Hello World!' component:'MyButton' props: title:'Discover docs' href:'http://react.semantic-ui.com' __dangerouslyEvalProps: onClick:'()=>alert("click works")' children:'click me' const myReactElements = ;
Advanced - Special properties
resourceprops (asyncprops) / thisprops / windowprops
The only different between resourceprops (asyncprops), thisprops and windowprops are the source of the transverse Object.
Resourceprops transverse an object that is manually passed (usually as a result of an asynchronous fetch all - hence the name asyncpropc).
Thisprops transverse anything bound to this.props
, a good example would be if you're storing and passing a user object on this.props.user
, pulling the username would be where you would use thisprops.
Windowprops transverse anything on the global window object, like the current page location window.location.href
.
Dynamic props are transversed by passing an array to the property value you want, so for a window's location (window.location.href
) the property value is accessed by an array to the href ['location','href']
where you omit the transverse object from the array path.
const traverseObject = user: name: 'rjx' description: 'react without javascript' stats: logins: 102 comments: 3 authentication: 'OAuth2';const testRJX = component: 'div' props: id: 'generatedRJX' className:'rjx' resourceprops: auth: 'authentication' username: 'user' 'name' children: component: 'p' props: style: color: 'red' fontWeight:'bold' asyncprops: title: 'user''description' children:'hello world' ;const RJXP = ;// => {// auth: 'OAuth2',// username: 'rjx'// } //finally resolves:const testRJX = component: 'div' props: id: 'generatedRJX' className:'rjx' auth: 'OAuth2' username: 'rjx' children: component: 'p' props: style: color: 'red' fontWeight:'bold' title:'react without javascript' children:'hello world' ;
__dangerouslyEvalProps / __dangerouslyBindEvalProps
The only difference between __dangerouslyEvalProps
and __dangerouslyBindEvalProps
is each __dangerouslyBindEvalProps
has to be a function, because it's returned as the bound instance of the function with this
.
const testVals = auth: 'true' username: '()=>(user={})=>user.name' ; const testRJX = Object; const RJXP = getEvalProps; const evalutedComputedFunc = RJXP; const evalutedComputedBoundFunc = RJXP; // expect(RJXP.auth).to.be.true; // expect(evalutedComputedFunc).to.eql('bob'); // expect(evalutedComputedBoundFunc).to.eql('bounded');
__functionProps
Function props merge onto rjx.props after evaluating each functon string.
const thisProp = debug: true window: 'printed' localStorage: 'gotItem' props: 'clicked' reduxRouter: 'pushed' 'poped' ;const rxjTest = component:'div' props: name:'test' __functionProps: onclick:'func:this.props.onClick' printPage: 'func:window.print' nav:'func:this.props.reduxRouter.push' ;const rxjObj = getFunctionProps;is;to;to;to;to;
comparisionprops
Comparison props are used to contionally show components if they're truthy. They compare an array of left and right side values, if they are all true, the component is rendered. If comparisonorprops:true
then only one condition needs to be true in order to render the component
//and conditionsrjx= comparisonprops: left: 'bigNum' operation:'lte' right:'smallNum' left: 'smallNum' operation:'<=' right:'bigNum' //or conditionsrjx= comparisonorprops:true comparisonprops: left: 'truthy' operation:'eq' right:'falsey' left: 'smallNum' operation:'eq' right:'smallNum' // All comparison operations
Advanced - Custom React Components & Lifecycle Functions
You can also create react components with lifecycle functions using getReactClassComponent
.
The only required function is a render function, the body of the function has to be valid rjx.
const MyCustomComponent = rjx_rjxComponents;const sampleRJX = component:'MyCustomComponent' props: status:'Amazing' ;const boundConfig = debug:true reactComponents: MyCustomComponent ;rjxrjxRender;
Console output after mounting
Log "this.props"status: "Amazing" children: {} someProp: 1 someOtherProp: 2"this.state"status: "not-loaded" name: "rjx test" customNumber: 1
Checkout the dist/example.html
for example usage.
Development
Note Make sure you have grunt installed
$ npm i -g grunt-cli jsdoc-to-markdown
For generating documentation
$ grunt doc$ jsdoc2md src/**/*.js > docs/api.md
Notes
Check out https://repetere.github.io/rjx/ for the full rjx Documentation
Testing
$ npm i$ grunt test
Contributing
Fork, write tests and create a pull request!
Example Browser Usage
RJX TEST
License
MIT