Using asyncprops
akonieczka opened this issue · 5 comments
My jsonx looks something like this...
const config = {
component: "Card",
children: [
{
component: "CardHeader",
props: {
title: "Test Header"
}
},
{
component: "CardContent",
children: [
{
component: "AttributeTable",
asyncprops: {
data: ["attributes"]
}
}
]
}
]
}
Above I have specified asyncprops on the AttributeTable component.
My traverseObject looks like this...
const data = {
attributes: [
{label: "test label 1", value: "test value 1"},
{label: "test label 2", value: "test value 2"},
{label: "test label 3", value: "test value 3"}
]
}
There is an "attributes" object which matches to the value specified in the asyncprops array.
The code looks like this...
const JSONXP = jsonx._jsonxProps.getJSONXProps({ jsonx: config, traverseObject: data });
When I inspect the result of JSONXP, it's just an empty object.
Hi, @akonieczka I just realized why you're seeing an empty object.
jsonx._jsonxProps.getJSONXProps
returns the computed props property of the jsonx object passed to the function.
In your config
jsonx object, getJSONXProps
returns an empty object because you passed:
{
component: "Card",
//There is no computed props property
children:[]
}
It returns an empty object by default: https://github.com/repetere/jsonx/blob/master/src/props.js#L102
export function getJSONXProps(options = {}) {
let { jsonx = {}, propName = 'asyncprops', traverseObject = {}, } = options;
return (jsonx[ propName ] && typeof jsonx[ propName ] === 'object')
? utilities.traverse(jsonx[ propName ], traverseObject)
: {};
}
Do you mind letting me know how you're looking to use jsonx?
If you want the rendered React Component then I believe you should be looking at jsonx. getReactElement
(https://github.com/repetere/jsonx/blob/master/src/main.js#L72)
Most people are using JSONX to actually render components, but if you're looking to get all the props, then there are other options to output JSX, JSONX, or plain JSON.
As a quick reference:
jsonx.outputHTML // Takes a JSONX JS object and outputs an HTML string ( Use ReactDOMServer.renderToString to render html from JSONX)
jsonx.outputJSX // Takes a JSONX JS object and outputs an JSX string ( used to typically write files)
jsonx.outputJSON // Takes a JSONX JS Object and outputs Plain JSON in the form of the arguments used for React.createElement. e.g. {type,props,children}
jsonx.getReactElement // Takes JSON JS Object and returns ReactElement using React.createElement
question: from @akonieczka "So it sounds like it only works for the top most parent component but doesn't work when defined on children components. The example shows it being used on a child component. Is that a mistake?"
answer: ah good catch, the example is incorrect.
Can you explain how you're attempting to use JSONX are you using it actually render components, or just to resolve props?
If you just want the props and not the actual react element then using jsonx.outputJSON
will recursively give you what you want.
If you want the actual react element then jsonx.getReactElement
will give you what you want.
jsonx.getReactElement({ component:'div', props:{ style:{color:'red'} }, children:'hello world', }) //equals
React.createElement('div',{ style:{color:'red'} },'hello world') // equals
<div style={{ color:'red' }}> hello world </div> // equals
Yes I am using getReactElement to render components and that part is working great.
Any chance to get an enhancement done so that you can use asyncprops on children?
@akonieczka check out https://github.com/repetere/jsonx/blob/master/manual/examples/resourceprops_asyncprops.html for a full working example.
I'm using a component library called Spectre for UI but other than that, it's an example for resource props.
here are some selected highlights:
const exampleComponent = {
component: 'Spectre.Grid.Grid',
children: [
{
component: 'div',
children: [
{
component: 'Spectre.Typography.H4',
children: 'Testing Deep Nested resourceprops (asyncprops)'
},
{
component: 'Spectre.Form.FormGroup',
children: [
{
component: 'label',
props: {
className: 'form-label',
htmlFor: 'input-1'
},
children: 'Form Input from resourceprops/asyncprops',
},
{
component: 'Spectre.Form.Input',
props: {
id: 'input-1'
},
resourceprops: {
defaultValue: [ 'deep', 'nested' ]
}
}
]
},
],
},
{
component: 'p',
asyncprops: {
children: [ 'deep', 'under' ],
}
}
]
};
jsonx.getReactElement({
jsonx: exampleComponent,
resources: {
deep:{
nested:'some data',
under:'works with resourceprops or asyncprops(alias)'
}
}
});
Thank you it's working now for me. Much appreciated!