Skip to content

Instantly share code, notes, and snippets.

@samsch
Created May 6, 2020 23:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samsch/8bd980135ea6f78e3e7fd0ee7f72b9d9 to your computer and use it in GitHub Desktop.
Save samsch/8bd980135ea6f78e3e7fd0ee7f72b9d9 to your computer and use it in GitHub Desktop.
Discord answer about how to do dynamic layouts or rendering

There are a couple ways to handle this. You could generate different bundles for each client, but if the bundle itself is what contains the generated layouts/data choices, then you would have to rebuild that bundle for each change, and for all clients for updates to the base code. I'm not going to say there couldn't be a case where that makes sense to do, but I can't really think of one. What would be more "normal" is to have your bundle build the layout based on a declarative data structure you can easily store in a database.

A really primitive form of this would be a simple conditional rendering:

// settings is coming from the DB
const Component = ({ settings }) => {
  if (settings.itemA) {
    return <ItemA />;
  } else {
    return <ItemB />;
  }
};

This concept can be scaled to pretty high complexity levels, but it very quickly can get difficult to manage, so I'd recommend to try to take the YAGNI (You Ain't Gonna Need It) path first, while keeping the code flexible so you can extend it later.

A more complex example might have a data structure like this:

[
  {
    "type": "GraphA",
    "options": { "option1": "center" },
    "data": []
  },
  {
    "type": "Row",
    "children": [
      {
        "type": "GraphB",
        "options": { "option1": "left" }
      },
      {
        "type": "Text",
        "children": "This is some text."
      }
    ]
  }
]

You can build a generic "renderer" component which takes the root and children and renders them to components.

The idea and concept are relatively straight-forward, but the devil really is in the details when building a system to do this. You'll have to figure out data loading and errors, how to keep the output accessible and usable, css layout stuff, and various decisions like whether you want to load all the possible components in the bundle, load them on-demand with import(), or try to do something more fancy to be more efficient (definitely just put them all in the bundle first to get things working).

I'd strongly recommend iterating over the concept several times. Take the ideas you have now and just build something. Write down the sticking points you ran into, and build it again (from scratch the first time at least) smarter. Rinse and repeat. You'll find things that work well, and keep them along the way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment