Experiment: dynamic React component replacement

A cool feature in Telescope is that third-party themes can override any previously-defined templates thanks to @aldeed’s template-extension package.

I wanted to replicate the same feature in React, but without depending on having everything in the global scope. It wouldn’t work with import because it doesn’t support dynamic paths, but it did work with require.

Here’s the result: https://gist.github.com/SachaG/8684ab46c5ea3dbe860e

It’s nothing groundbreaking, but I’m just curious to hear if anybody else has been working on similar ideas?

Looks great to me, plus you get the benefit of being able to control which components are replaceable. I think there are ways of reducing the boilerplate though, maybe by having a wrapper function or something.

Check this project also: https://github.com/gaearon/react-proxy

Hmm @sacha does this cause a partial/full rerender or does the first load already happen with the override?

I’m not sure, but the idea is that the component being overridden would never be rendered at all, hopefully.

Thanks! Yeah I’m sure this could be improved. Happy to hear ideas :slight_smile:

Actually, it looks like this doesn’t work as intended just yet. const PostItem = Telescope.getComponent("PostItem"); doesn’t get reevaluated even if you override the component later on in another package.

So the only way to make this work would be to ensure that the package doing the overriding gets loaded before whichever package contains the component. But I’m not sure there’s a way to specify that with Meteor’s package system?

I guess one way would be to manually place the overriding package first in .meteor/packages. But that feels a little hacky…


EDIT

So I found a fix, which is simply to put the require call inside the render function:

PostList = props => {

  const PostItem = Telescope.getComponent("PostItem");

  return (
    <div className="postList">
      {props.posts.map(post => <PostItem {...post} key={post._id}/>)}
    </div>
  )

};

Seems obvious looking back :slight_smile:

It does feel a bit weird since dependencies are always usually listed at the very top of a file, are there any downsides to this approach?

Not really but neither approach is “pure” since both have an external dependency whereas you could switch out the const assignment for an argument of the function.

And by doing that, you could work your way towards a more direct api where you customize the argument.

Ps: my initial hesitation was about the app rendering the first version and then the second instead of just the second.