{"action":"created","issue":{"url":"https://api.github.com/repos/riot/riot/issues/2594","repository_url":"https://api.github.com/repos/riot/riot","labels_url":"https://api.github.com/repos/riot/riot/issues/2594/labels{/name}","comments_url":"https://api.github.com/repos/riot/riot/issues/2594/comments","events_url":"https://api.github.com/repos/riot/riot/issues/2594/events","html_url":"https://github.com/riot/riot/issues/2594","id":324752410,"number":2594,"title":"[Discussion] Is the `yield` tag appropriate for component composition?","user":{"login":"Kangaroux","id":2302541,"avatar_url":"https://avatars1.githubusercontent.com/u/2302541?v=4","gravatar_id":"","url":"https://api.github.com/users/Kangaroux","html_url":"https://github.com/Kangaroux","followers_url":"https://api.github.com/users/Kangaroux/followers","following_url":"https://api.github.com/users/Kangaroux/following{/other_user}","gists_url":"https://api.github.com/users/Kangaroux/gists{/gist_id}","starred_url":"https://api.github.com/users/Kangaroux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kangaroux/subscriptions","organizations_url":"https://api.github.com/users/Kangaroux/orgs","repos_url":"https://api.github.com/users/Kangaroux/repos","events_url":"https://api.github.com/users/Kangaroux/events{/privacy}","received_events_url":"https://api.github.com/users/Kangaroux/received_events","type":"User","site_admin":false},"labels":[{"id":224827161,"url":"https://api.github.com/repos/riot/riot/labels/discussion","name":"discussion","color":"fef2c0","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-05-20T23:37:27Z","updated_at":"2018-05-29T10:40:06Z","closed_at":null,"author_association":"NONE","body":"**tl;dr:** is the `yield` tag appropriate for [component composition](https://reactjs.org/docs/composition-vs-inheritance.html), similar to React's `props.children`?\r\n\r\nLet me start this discussion by quickly recalling the `yield` tag. Consider this very basic tag which renders any nested HTML:\r\n\r\n```html\r\n<my-tag>\r\n  <yield />\r\n\r\n  sayHello() {\r\n    console.log(\"Hello!\");\r\n  }\r\n</my-tag>\r\n```\r\n\r\nIf you use the `yield` tag, any reference to `this` inside the yielding block refers to the tag which has the `yield` tag. This makes sense if you are directly rendering the tag onto the page in the HTML:\r\n\r\n```html\r\n<body>\r\n  <my-tag>\r\n    <button onClick={ this.sayHello }>Click me!</button>\r\n  </my-tag>\r\n</body>\r\n```\r\n\r\n`this` will reference `my-tag`, and clicking the button will print \"Hello!\" in the console. No surprises there.\r\n\r\nNow a more practical example:\r\n\r\n```html\r\n<!-- Generic modal tag defines the layout -->\r\n<modal>\r\n  <div class=\"modal\">\r\n    <div class=\"modal-title\">{ opts.title }</div>\r\n    <div class=\"modal-body\">\r\n      <yield />\r\n    </div>\r\n  </div>\r\n</modal>\r\n\r\n\r\n<!-- A \"concrete\" modal which uses the layout -->\r\n<cool-modal>\r\n  <modal title=\"My Cool Modal\">\r\n    <button onClick={ this.sayHello }>Click me!</button>\r\n  </modal>\r\n\r\n  sayHello() {\r\n    console.log(\"Hello!\");\r\n  }\r\n</cool-modal>\r\n```\r\n\r\nIn this example, when the user clicks the button, nothing happens, because `this` refers to `<modal>` and not the parent `<cool-modal>`.\r\n\r\nKnowing this, it's simple enough to change the event handler to `onClick={ this.parent.sayHello }`. This raises a few concerns:\r\n- You need to mix `this` with `this.parent` if other parts of the tag are outside of `<modal>`\r\n- Deep nesting causes `this.parent.parent...` which is very hacky and difficult to maintain.\r\n\r\nMy proposal would be to have an additional keyword similar to `this` (e.g. `child`) which is scoped to the tag which contains it, and keep the `this` keyword consistent regardless of nesting.\r\n\r\n```html\r\n<my-tag>\r\n  <!-- refers to `my-tag.var` -->\r\n  { this.var }\r\n  <nested>\r\n    <!-- still refers to `my-tag.var` -->\r\n    { this.var }\r\n    <nested2>\r\n      <!-- refers to `nested2.otherVar` -->\r\n      { child.otherVar }\r\n    </nested2>\r\n  </nested>\r\n</my-tag>\r\n```\r\n\r\n3. Which version of Riot does it affect?\r\n\r\n3.10.1\r\n\r\n4. How would you tag this issue?\r\n\r\n  - [X] Question\r\n  - [ ] Bug\r\n  - [X] Discussion\r\n  - [ ] Feature request\r\n  - [ ] Tip\r\n  - [X] Enhancement\r\n  - [ ] Performance\r\n"},"comment":{"url":"https://api.github.com/repos/riot/riot/issues/comments/392732355","html_url":"https://github.com/riot/riot/issues/2594#issuecomment-392732355","issue_url":"https://api.github.com/repos/riot/riot/issues/2594","id":392732355,"user":{"login":"RuXxar","id":4342161,"avatar_url":"https://avatars2.githubusercontent.com/u/4342161?v=4","gravatar_id":"","url":"https://api.github.com/users/RuXxar","html_url":"https://github.com/RuXxar","followers_url":"https://api.github.com/users/RuXxar/followers","following_url":"https://api.github.com/users/RuXxar/following{/other_user}","gists_url":"https://api.github.com/users/RuXxar/gists{/gist_id}","starred_url":"https://api.github.com/users/RuXxar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RuXxar/subscriptions","organizations_url":"https://api.github.com/users/RuXxar/orgs","repos_url":"https://api.github.com/users/RuXxar/repos","events_url":"https://api.github.com/users/RuXxar/events{/privacy}","received_events_url":"https://api.github.com/users/RuXxar/received_events","type":"User","site_admin":false},"created_at":"2018-05-29T10:40:06Z","updated_at":"2018-05-29T10:40:06Z","author_association":"NONE","body":"I've also ran into this issue quite a few times. and it's always a pain trying to make a structure out of this that makes sense.\r\nIt often leads to sneaky bugs and bad/awkward/hard to maintain code structure.\r\n\r\nI feel like the proposed solution is a step in the right direction.\r\nHaving one keyword that always refers to the tag, and one keyword that refers to the local context would make a lot of the pain go away when composing tags like this."}}
{"actor":{"display_login":"RuXxar"}}