Open kwasniew opened 4 years ago
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Avoiding Prop Driling with Children</title>
<link rel="stylesheet" href="https://unpkg.com/sakura.css/css/sakura.css" type="text/css">
<script type="module">
import {app} from "https://unpkg.com/hyperapp?module";
import html from "https://unpkg.com/hyperlit?module";
const state = {user: "matt"};
const GrandParent = (children) => html`<div>GrandParent ${children}</div>`
const Parent = (children) => html`<div>Parent ${children}</div>`
const Child = user => html`<div>${user}</div>`;
const view = state => GrandParent(Parent(Child(state.user)));
app({
init: state,
view,
node: document.getElementById("app")
});
</script>
</head>
<body>
<main>
<div id="app"></div>
</main>
</body>
</html>
Inspired by: https://www.youtube.com/watch?time_continue=941&v=3XaXKiXtNjw&feature=emb_logo
I would say the opposite. Using children to avoid prop drilling looks to me like it has really specific situations when it can be used. Even in the video he still says that context is better for truly global data like the theme, user preferences (and probably user as it's a silly example).
The biggest disadvantage is that you lose abstraction. Now imagine GrandParent
is used 50 times in your codebase. The Parent
is even more applicable and you find 200+ matches.
In my experience when you get into a bigger project - especially if it's actively worked on by a bigger team the only practical solution is to use some kind of context.
Of course, bigger refactoring would get you the same thing. But, if we're talking about getting the same thing then it just doesn't make it worth it.
Something I'm not sure about is when does it stop? When I take this example further it seems like my whole view would be a super complex and super long file with really deeply nested views to avoid prop drilling. It doesn't sound maintainable to me.
I was thinking about proposing some rule of thumb rules like:
I'm struggling to figure out when I would recommend render props (or in this case render children pattern—I can't see a difference).
I'm sorry but I struggle to think through code examples that are abstract. Wouldn't you mind using more real-life views?
import {app} from "https://unpkg.com/hyperapp?module";
import html from "https://unpkg.com/hyperlit?module";
const state = {theme: "ligth"};
const Root = (children) => html`<div>App ${children}</div>`
const Header = (children) => html`<div>Header ${children}</div>`
const Logo = theme => html`<div>${theme}</div>`;
const view = state => Root(Header(Logo(state.user)));
app({
init: state,
view,
node: document.getElementById("app")
});
The benefit of my examples (for me) is that it makes it more obvious for me that I would struggle to work with this pattern probably beyond maybe 20 lines of view code. It's a guess on my side, but I'm pretty sure there would be a limit to the practice.
What I'm thinking is that we need to have a couple of solutions.
I need to think about it. But the moment you start using context you loose local reasoning capability. You always have some state at a distance. This is a problem the Reader monad solves so maybe some inspiration from there.
https://github.com/jorgebucaran/hyperapp/issues/941