Creating React Components And Component Libraries
JSONX can generate function, class, dynamic, and form components from JSONX definitions. Use this when component definitions need to be data. For most application code, bundling components normally and registering them through reactComponents or componentLibraries is simpler and faster.
- 1. Function Components - Use
jsonx._jsonxComponents.getReactFunctionComponentand JXM to create React function components with JSON. - 2. Class Components - Use
jsonx._jsonxComponents.getReactClassComponentand JXM to create React class components with JSON. - 3. Dynamic Components - Use
jsonx._jsonxComponents.DynamicComponentto fetch data and render a JSONX component after the data resolves. - 4. Form Components - Use
jsonx._jsonxComponents.FormComponentto create forms with React Hook Form.
1. Function Components
There are two ways to create function components: jsonx._jsonxComponents.getReactFunctionComponent and jsonx._jsonxComponents.makeFunctionComponent. makeFunctionComponent is a shortcut for passing a regular JavaScript function. JSONX reads that function and converts it into the arguments used by getReactFunctionComponent.
function myComponent(){
const [count,setCount] = useState() // you can use any React hook inside your function
const exposeprops = {count,setCount}; // define what props should be available to the rendered component
return {// return JSONX JSON
component:'div',
passprops:true, //set to true so you can pass 'count' and 'setCount' to child elements
children: [
{ component:'span', children:'Clicked Count' },
{
component:'input',
props:{ defaultValue:0 },
thisprops:{ value:['count'], },
},
{
component:'button',
__dangerouslyBindEvalProps:{
onClick(count,setCount){
setCount(count+1);
},
},
children:'Click me'
}
]
}
}
jsonx._jsonxComponents.makeFunctionComponent(myComponent) // returns a React function component
JSONX exposes jsonx._jsonxComponents.getReactFunctionComponent for creating React function components.
export function getReactFunctionComponent(
reactComponent: JXM_JSON,
functionBody: string,
options = {},
): ReactComponentLike
getReactFunctionComponent takes three arguments:
reactComponent, which contains the JXM JSON for rendering the function component.functionBody, which is a string body for the function component. If you use hooks or need to expose values from inside the component, assign those values to anexposepropsvariable.options, which customizegetReactFunctionComponent.
const hookFunctionComponent = jsonx._jsonxComponents.getReactFunctionComponent(
//reactComponent
{
component:'div',
passprops:true,
children:[
{
component:'button',
__dangerouslyBindEvalProps:{
onClick:function(clicks,set_click){
set_click(clicks+1);
},
},
thisprops:{
clicks:['clicks'],
set_click:['set_click']
},
children:'Click Me',
},
{
component:'span',
children:' Clicks: '
},
{
component:'span',
thisprops:{
_children:['clicks'],
}
}
]
},
//functionBody
`
const [clicks, set_click] = useState(0);
const exposeprops = {clicks,set_click};
`,
//options
{
name:'hookFunctionComponent',
});
Example Function Components
2. Class Components
JSONX exposes jsonx._jsonxComponents.getReactClassComponent for creating React class components. getReactClassComponent uses createReactClass.
export function getReactClassComponent(
reactComponent = {},
options = {},
): ReactComponentLike
getReactClassComponent takes two arguments: reactComponent, which contains the arguments passed to createReactClass, and options.
The only required function in the reactComponent object is render. The render body must be valid JXM JSON. Other lifecycle or helper methods use a body value for the function body and an arguments array for the function parameters.
const reactComponent = {
//
// Initialization function
//
getInitialState:{
body:'return { status:"not-loaded", name:"jsonx test", customNumber:1, }',
arguments:[],
},
getDefaultProps:{
body:'return { someProp:1, someOtherProp:2, status:"original status" }',
arguments:[],
},
componentDidMount:{
body:`console.log('mounted', 'this.props',this.props, 'this.state',this.state)`,
arguments:[],
},
componentWillUnmount:{
body:`console.log('unmounted',this.props)`,
arguments:[],
},
//
// State change functions
//
shouldComponentUpdate:{
body:'console.log("should update component",{nextProps,nextState}); return true;',
arguments:['nextProps', 'nextState']
},
componentWillUpdate:{
body:'console.log("will update component",{nextProps,nextState}); return true;',
arguments:['nextProps', 'nextState']
},
componentDidUpdate:{
body:'console.log("did update component",{prevProps,prevState}); return true;',
arguments:['prevProps', 'prevState']
},
//
// Prop change functions
//
componentWillReceiveProps: {
body:'console.log("will receive props",{nextProps}); return true;',
arguments:['nextProps']
},
//
// RENDER IS THE ONLY ***REQUIRED*** FUNCTION
//
render:{
body:{
component:'p',
props:{
status:'from inline prop'
},
passprops:true,
children:[
{
component:'span',
children: 'My Custom React Component Status: ',
},
{
component:'span',
thisprops:{
children:['status']
}
}
]
},
}
};
const options = {
name:'MyCustomComponent',
};
const MyCustomComponent = jsonx._jsonxComponents.getReactClassComponent(reactComponent,options);
const JXM = {
component:'MyCustomComponent',
props:{
status:'Amazing',
}
};
const boundConfig = {
debug:true,
reactComponents:{
MyCustomComponent,
}
};
jsonx.jsonxRender.call(boundConfig, {
jsonx: JXM,
querySelector:'#main', });
Console output after mounting
[Log] mounted (4)
"this.props"
{status: "Amazing", children: {}, someProp: 1, someOtherProp: 2}
"this.state"
{status: "not-loaded", name: "jsonx test", customNumber: 1}
Example Class Components
3. Dynamic Components
JSONX has a helper component called DynamicComponent. Use it when a JSONX component needs to fetch data before rendering.
The common use case is a dashboard or page where sections load data independently. DynamicComponent handles this without requiring Suspense or lazy loading.
After the data is fetched, JSONX renders the jsonx object passed in props. The resolved data is available as resourceprops.DynamicComponentData.
const JXM = {
component: 'DynamicComponent',
props: {
useCache: boolean;
cacheTimeout: number;//milliseconds
loadingJSONX: jsonx;
loadingErrorJSONX: jsonx;
cacheTimeoutFunction: () => void,
jsonx: jsonx;
transformFunction: (data: any) => any,
fetchURL: string;
fetchOptions: any;
fetchFunction: (fetchURL: string, fetchOptions: any)=>Promise,
}
};
const dynamicComponent = jsonx.getReactElementFromJSONX({
component:'DynamicComponent',
props:{
fetchURL:'/path/to/some/data',
jsonx:{
component:'p',
children:'loaded data',
}
}
});
Example Dynamic Components
4. Form Components
JSONX has a helper component called FormComponent. FormComponent creates forms with React Hook Form without requiring another form wrapper.
Form components work by creating a function component that uses the useForm hook. You can customize useForm with schema validation through Yup or other supported useForm options.
Pass the form fields through the formComponent JXM property. By default, FormComponent wraps the fields with form onSubmit={handleSubmit(props.onSubmit)}. Replace that wrapper with formWrapperComponent when you need custom form markup.
FormComponent adds a ReactHookForm component library with Controller and ErrorMessage. Methods returned from the useForm hook are bound to this.reactHookForm. Use that context when JSONX needs access to registration, errors, or other React Hook Form behavior.
const JXM = {
component: 'FormComponent',
props: {
hookFormOptions: {},// settings for react-hook-form's useForm hook
formComponent: jsonx,
onSubmit:(formdata: any) => any,
formWrapperComponent: jsonx,
}
};
const formComponent = jsonx.getReactElementFromJSONX({
component:'FormComponent',
props:{
onSubmit: (data) => { console.log({ submitData: data }) },
formComponent:{
component: "input",
props: { type: "text", name: "username", placeholder: "username" },
thiscontext:{ ref:['reactHookForm','register'] },
},
}
});