{"id":292329,"date":"2019-07-03T07:36:24","date_gmt":"2019-07-03T14:36:24","guid":{"rendered":"https:\/\/css-tricks.com\/?p=292329"},"modified":"2019-07-03T07:36:24","modified_gmt":"2019-07-03T14:36:24","slug":"haunted-hooks-for-web-components","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/haunted-hooks-for-web-components\/","title":{"rendered":"Haunted: Hooks for Web Components"},"content":{"rendered":"
I was just chatting with Dave<\/a> and he told me about Haunted<\/a>. It’s hooks, but for native web components<\/a>! Pretty cool. I think the existence of stuff like this makes using web components more and more palatable — particularly in that totally-native no-build-step-needed-at-all kinda way. <\/p>\n <\/p>\n I get that there are all sorts of issues with web components<\/a>, but the things that typically turn me away from them are a lack of nice templating and rerendering<\/strong> and no state management<\/strong>. <\/p>\n But we can knock those two out right quick these days…<\/p>\n First, making a component like Then we could add some state<\/a> with hooks:<\/p>\n The CodePen Challenge this week<\/a> is using the Star Wars API<\/abbr>, so let’s make a fetch request and use that to fill state. That’s a great use case for useEffect<\/a>. <\/p>\n That’s a proper little web component! <\/p>\n \n See the Pen I was just chatting with Dave and he told me about Haunted. It’s hooks, but for native web components! Pretty cool. I think the existence of stuff like this makes using web components more and more palatable — particularly in that totally-native no-build-step-needed-at-all kinda way.<\/p>\n","protected":false},"author":3,"featured_media":292359,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[4],"tags":[],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/07\/lots-of-bubbles.png?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":340901,"url":"https:\/\/css-tricks.com\/links-on-web-components\/","url_meta":{"origin":292329,"position":0},"title":"Links on Web Components","date":"May 26, 2021","format":false,"excerpt":"How we use Web Components at GitHub \u2014 Kristj\u00e1n Oddsson talks about how GitHub is using web components. I remember they were very early adopters, and it says here they released a <my-app><\/code> is perfectly comfortable<\/a>:<\/p>\n
import { html } from \"https:\/\/unpkg.com\/lit-html\/lit-html.js\";\r\nimport { component } from \"https:\/\/unpkg.com\/haunted\/haunted.js\";\r\n\r\nfunction App() {\r\n return html`\r\n <div class=\"module\">\r\n Hello, World!\r\n <\/div>\r\n `;\r\n}\r\n\r\ncustomElements.define(\"my-app\", component(App));<\/code><\/pre>\n
import { html } from \"https:\/\/unpkg.com\/lit-html\/lit-html.js\";\r\nimport { component, useState} from \"https:\/\/unpkg.com\/haunted\/haunted.js\";\r\n\r\nfunction App() {\r\n const [name, setName] = useState(\"Chris\");\r\n return html`\r\n <div class=\"module\">\r\n Hello, ${name}!\r\n <\/div>\r\n `;\r\n}\r\n\r\ncustomElements.define(\"my-app\", component(App));<\/code><\/pre>\n
import { html } from \"https:\/\/unpkg.com\/lit-html\/lit-html.js\";\r\nimport { component, useState, useEffect } from \"https:\/\/unpkg.com\/haunted\/haunted.js\";\r\n\r\nfunction App() {\r\n \r\n const [planets, setPlanets] = useState([]);\r\n useEffect(() => {\r\n fetch('https:\/\/swapi.co\/api\/planets\/?page=2')\r\n .then(response => {\r\n return response.json();\r\n })\r\n .then(data => {\r\n let planets = data.results;\r\n \/\/ remove ones with no diameters\r\n planets = planets.filter(planet => planet.diameter !== \"0\");\r\n setPlanets(planets);\r\n });\r\n }, []);\r\n\r\n return html`\r\n <style>\r\n \/* Shadow DOM styles *\/\r\n <\/style>\r\n <div class=\"all-planets\">\r\n ${planets.map(planet => html`\r\n <div class=\"planet\" style=\"--dia: ${planet.diameter}px\">\r\n <span class=\"planet-name\">\r\n ${planet.name}\r\n <\/span>\r\n <\/div>\r\n `)}\r\n <\/div>\r\n `;\r\n}\r\n\r\ncustomElements.define(\"my-app\", component(App));<\/code><\/pre>\n
\n Star Wars API with Haunted.js<\/a> by Chris Coyier (@chriscoyier<\/a>)
\n on CodePen<\/a>.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":" like you would do in Bootstrap or