near / react-on-chain

Improved execution layer for NEAR decentralized frontend components
https://roc-docs.near.dev/
23 stars 5 forks source link

Components defined as arrow functions cannot import child Components #421

Open calebjacob opened 2 weeks ago

calebjacob commented 2 weeks ago

With the awesome work @andy-haynes did to refactor how props can be passed more naturally (without nesting them in a props object), I realized we could start using a more natural typed component syntax that provides better type safety and ergonomics overall.

Here's an example of the syntax that I'm describing:

import s from './styles.module.css';

type Props = {
  message?: string;
};

const TypedComponentChild: BWEComponent<Props> = ({ message = 'default message' }) => {
  return (
    <div className={s.wrapper}>
      <p>This is the child message: {message}</p>
    </div>
  );
}

export default TypedComponentChild;

Instead of having to do a cast explicitly for the export - which could be easy to forget or confusing since it's not a very common pattern (casting combined with an export statement):

export default RocChildTest as BWEComponent<Props>;

However, I ran into an interesting bug that I documented with a Loom: https://www.loom.com/share/398d0a396f1c43b8af203c14ec932a1b

andy-haynes commented 2 weeks ago

The type annotation is a red herring, the custom Babel plugin should be running after that's been stripped out anyway.

The underlying issue is the Babel plugin's use of arguments to facilitate imports. In the current implementation, a parent Component needs to reference its own props to render a (trusted) child Component. This is how a trusted Component knows its ancestry relative to a container, analogous to a prototype chain for trusted Components.

I would need to dig into this deeper to figure out where there's some give. In the meantime, you would need to use function to support child imports.