Exclusive tips every week

Join 11,067 other Vue devs and get exclusive tips and insights delivered straight to your inbox, every week.

    Picture of Michael Thiessen

    👋Hey friend! I work hard to send you amazing stuff each week.

    — Michael

    I really love and enjoy reading these emails.

    You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.

    Fabian Beer

    Here's my latest newsletter

    🔥 (#154) Newsletter 2024-02-28


    🔥 Using Render Functions for Dynamic Component Logic

    Render functions provide a powerful and flexible way to programmatically define the output of components.

    This approach is particularly useful when you need more control over the rendering process than templates offer.

    Consider a scenario where you're building a custom If...Else component that conditionally renders content based on a given condition (we're just doing this for fun, okay?)

    Here's a simplified example of how you might use a render function in an If component:

    export default {
    props: ['val'],
    setup(props, { slots }) {
    return () => {
    const children = [];
    if (props.val && slots.true) {
    } else if (!props.val && slots.false) {
    return children;

    In this example, the If component takes a val prop to determine which slot to render — true or false. The render function checks props.val and dynamically decides which slot to render based on its value.

    Render functions are especially useful when:

    • You need to programmatically construct component output based on complex conditions.
    • You're building higher-order components that manipulate their children in ways that aren't straightforward with templates.
    • You want to leverage JavaScript's full power to dynamically generate component structures.

    While render functions offer great power and flexibility, they come at the cost of reduced readability and simplicity compared to template syntax.

    So it's generally recommended to use them only when necessary, keeping the balance between functionality and maintainability.

    🔥 Nesting Reactive Objects

    Here’s a nuance to nesting reactive objects that’s tripped me up.

    Nesting a ref in a reactive array keeps everything reactive as expected:

    const arr = reactive([]);
    setTimeout(() => (arr[0].value = 'nothing'), 1000);

    But putting this ref inside a non-reactive object breaks this reactivity:

    const arr = reactive([]);
    text: ref('hello'),
    text: ref('world'),
    setTimeout(() => (arr[0].value = 'nothing'), 1000);

    I gave a hint in that last sentence — this is because it’s being wrapped in a non-reactive object. The trail of reactivity goes cold once we hit this object, but only because we’re accessing the text property through the non-reactive object.

    If we instead access the ref directly, we’re able to trigger a reactive update as expected:

    const arr = reactive([]);
    const one = ref('hello');
    const two = ref('world');
    text: one,
    text: two,
    // This triggers the update correctly
    setTimeout(() => (one.value = 'nothing'), 1000);

    Of course, this isn’t about refs in particular. All we need is to keep the reactivity alive, which we can also achieve using reactive.

    🔥 Using unstorage in Nuxt 3

    Nitro, the server that Nuxt 3 uses, comes with a very powerful key-value storage system:

    const storage = useStorage();
    // Save a value
    await storage.setItem('some:key', value);
    // Retrieve a value
    const item = await storage.getItem('some:key');

    It’s not a replacement for a robust database, but it’s perfect for temporary data or a caching layer.

    One great application of this “session storage” is using it during an OAuth flow.

    In the first step of the flow, we receive a state and a codeVerifier. In the second step, we receive a code along with the state again, which let’s us use the codeVerifier to verify that the code is authentic.

    We need to store the codeVerifier in between these steps, but only for a few minutes — perfect for Nitro’s storage!

    The first step in the /oauth endpoint we store the codeVerifier:

    // ~/server/api/oauth
    // ...
    const storage = useStorage();
    const key = `verifier:${state}`;
    await storage.setItem(key, codeVerifier);
    // ...

    Then we retrieve it during the second step in the /callback endpoint:

    // ~/server/api/callback
    // ...
    const storage = useStorage();
    const key = `verifier:${state}`;
    const codeVerifier = await storage.getItem(key);
    // ...

    A simple and easy solution, with no need to add a new table to our database and deal with an extra migration.

    This just scratches the surface. Learn more about the unstorage package that powers this: https://github.com/unjs/unstorage

    📜 SSR Safe Dynamic IDs in Vue

    Dynamic IDs are useful for testing, but can get tricky with SSR.

    In this article we'll make a directive to do this easily, in both vanilla Vue and in Nuxt.

    Check it out here: SSR Safe Dynamic IDs in Vue

    💬 Frustation

    "Give someone a program, you frustrate them for a day; teach them how to program, you frustrate them for a lifetime." — David Leinweber

    🧠 Spaced-repetition: Debugging Templates

    The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬

    Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.

    If you ever need to debug what’s happening inside of a template, you can just throw in a function:

    <div v-for="i in 4" :key="i">
    {{ log(i) }}
    {{ i + 1 }}

    Vue will execute anything within the curly braces as Javascript, so this function is called normally.

    It can be whatever you want. Set it to console.log if you just want to log out some values:

    const log = console.log;

    Or add in a debugger statement so you can step through the code one line at a time and inspect the variables more closely:

    const log = (val) => {

    If we want global access to a debugging utility, we can use the globalProperties field on our app config:

    app.config.globalProperties.$log = console.log;

    Now, we can use this $log method in whatever component we want:

    p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components

    Here's what others are saying

    I'm starting to think that your newsletter is one of the best things that happened to me this year. I just love these emails.
    Stanislaw Gregor
    I'm somewhere in the upper-middle level at Vue, and I never miss an email you and always find something cool when reading!
    Eduard Climov
    This is the first time where I'm actually enjoying email newsletters. I like your format a lot.
    Fahmi Alfituri
    You have great content in your emails. I seriously learn something from every one of them.
    Titus Decali
    Just wanted to say I enjoy these emails. They encourage me to constantly improve my craft. Fantastic work.
    Joe Radman
    Thanks for another beautiful tip 🙏
    Victor Martins Onuoha
    Loving these, and the spaced repetition.
    Mark Goldstein
    I really enjoy reading your emails, because I love Vue. Thanks for these emails.
    Arturo Espinoza
    I really love and enjoy reading these emails. You are one of the most pro VueJS devs I know, and I am happy that you share this knowledge.
    Fabian Beer
    THANK YOU! I did not know about the deep property, so I assumed you simply couldn't watch objects.
    Darryl Noakes
    I really must say you are doing a really great job. Now I am aware of a cleaner and more performant way to use Tailwind. Thanks a lot!
    Henry Eze
    Thank you so much, I really enjoy and appreciate your emails.
    Carlos Gonzalez
    Thanks for sharing great Vue tips.
    Fernando Navarro
    I really enjoy these tips.
    Martin H
    Thank you so much for the weekly Vue education. Thanks and live on longer to educate us more.
    Kabolobari Benakole
    I look forward to your emails every week. This week was something I knew, but I like to be reminded of. Thanks for keeping it up!
    Nathan Strutz
    Thank you for your weekly emails. I always look forward to learning a new tip about Vue or at least relearning old tips :)
    Colin Johnson
    I have really been enjoying your weekly emails, and I also got my two team members to join in on the fun as well.
    Keith Dawson
    Thank you for your newsletter, your explanations have very concise examples and I like it.
    Nicolas Decayeux
    Thanks A LOT for your great work!!! One of the few newsletters that I let pass!
    Martin Tillmann

    Want to level up your Vue skills?

    With over two million reads and 11,067 subscribers, you've come to the right place.

    Subscribe now to get exclusive insights and tips every week.