Support passing children to sandboxed Components
It's a very common React pattern to pass children into a component. You'd set up your component to take in a children: ReactNode prop like so:
import type { ReactNode } from 'react';
import s from './styles.module.css';
type Props = {
children?: ReactNode;
};
function Parent({ children }: Props) {
return (
<div className={s.wrapper}>
{children}
</div>
);
}
export default Parent as BWEComponent<Props>;
You would then expect to use <Parent> like so:
import Parent from './Parent';
import s from './styles.module.css';
function Root() {
return (
<div className={s.wrapper}>
<Parent>
<p>Hello!</p>
</Parent>
</div>
);
}
export default Root as BWEComponent;
However, this exact syntax isn't currently supported due to all props needing to be passed through an explicit props object. This will be resolved here: https://github.com/near/bos-web-engine/issues/261
Until that issue is resolved, you can use this syntax - and everything will work if we only pass in native DOM components (eg: p, div, etc):
<Parent props={{
children: <p>Hello!</p>
}} />
However, it's very common that we'd need to pass in our own component as a child. Let's set up a new component:
import s from './styles.module.css';
function Child() {
return (
<div className={s.wrapper}>
<p>I am a child</p>
</div>
);
}
export default Child as BWEComponent;
Then we update our root component to pass <Child> to <Parent> like so:
import Parent from './Parent';
import Child from './Child';
import s from './styles.module.css';
function Root() {
return (
<div className={s.wrapper}>
<Parent props={{
children: (
<div>
<Child />
<p>Hello there...</p>
</div>
)
}} />
</div>
);
}
export default Root as BWEComponent;
The engine throws the following error saying Child is an unrecognized component:
This is a very common use case when building out more robust React applications. For a more concrete example, imagine you needed to build a <Theme> component that can be used to wrap multiple pages/components and provide CSS variables to all of its children. In an ideal world, the BOS engine would support the following:
import type { ReactNode } from 'react';
import s from './styles.module.css';
type Props = {
children?: ReactNode;
};
function Theme({ children }: Props) {
return (
<div className={s.wrapper}>
{children}
</div>
);
}
export default Theme as BWEComponent<Props>;
.wrapper {
--primary-color: red;
}
import Theme from './Theme';
import Child from './Child';
import s from './styles.module.css';
function PageOne() {
return (
<Theme>
<p className={s.text}>Hello!</p>
<Child />
</Theme>
);
}
export default PageOne as BWEComponent;
.text {
color: var(--primary-color);
}
This is working for trusted Components since the introduction of the Babel plugin. Sandboxed Components still have some difficulty, since <Component /> is a stub and not an actual React Component. It doesn't look like much work to get it in parity though.
import Child from './Child';
import Parent from './Parent';
import s from './styles.module.css';
function Root() {
return (
<div className={s.wrapper}>
<Parent bwe={{trust:{mode:'trusted'}}}>
<Child />
<p>Hello!</p>
</Parent>
</div>
);
}
export default Root as BWEComponent;
candidate to kick out to P1