Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

How to quickly detect the hover event in Vue.js

To detect mouse hover in Vue.js, use a hover state variable and the mouseenter & mouseleave events to detect when the mouse enters and leaves the element’s bounds.

App.vue
<template> <div @mouseenter="hover = true" @mouseleave="hover = false"></div> </template> <script> export default { data() { return { hover: false, }; }, }; </script>

The mouseenter event runs when the mouse pointer enters the bounds of an element, while mouseleave runs when it leaves.

We could also listen to the mouseover event to detect hover, this event runs for an element and every single one of its ancestor elements in the DOM tree (i.e. it bubbles) and this could cause serious performance problems in deep hierarchies. mouseenter doesn’t bubble so we can use it without worrying about this.

Change style on hover in Vue.js

To change the style of an element on hover in Vue.js, we can combine the hover state variable and the :class directive:

App.vue
<template> <div @mouseenter="hover = true" @mouseleave="hover = false" class="div" :class="{ 'div-hover': hover }" ></div> </template> <script> export default { data() { return { hover: false, }; }, }; </script> <style> .div { background-color: blue; width: 200px; height: 100px; } .div-hover { background-color: yellow; } </style>
Changing color on mouse hover in Vue.js.

Display another element on hover in Vue.js

We could also display another element in the UI when we detect hover. For example: a tooltip to display more info on a particular UI element.

To do this, you can pass the state variable to a v-if state directive you set on the element. This ensures that the element only displays when the hover state is true.

App.vue
<template> <button @mouseenter="hover = true" @mouseleave="hover = false" class="div" :class="{ 'div-hover': hover }" > Button </button> <p v-if="hover">Tooltip</p> </template> <script> export default { data() { return { hover: false, }; }, }; </script>
Displaying another element on hover.

Detect hover on Vue component

You can also use the mouseenter and mouseleave approach to detect hover on a custom Vue component.

components/StyledButton.vue
<template> <div> <button>Styled button</button> </div> </template> <style> button { height: 30px; width: 100px; background-color: lightgreen; } </style>
App.vue
<template> <styled-button @mouseenter="hover = true" @mouseleave="hover = false" ></styled-button> <p v-if="hover">Tooltip</p> </template> <script> import StyledButton from './components/StyledButton.vue'; export default { components: { StyledButton, }, data() { return { hover: false, }; }, }; </script>
Detecting mouse hover on a Vue.js custom component.

If you’re using Vue 2.x, you’ll need to use the .native event modifier to listen for native DOM events on the Vue component:

Vue
<styled-button @mouseenter.native="hover = true" @mouseleave.native="hover = false" ></styled-button>

Key takeaways

  • Detect mouse hover in Vue.js using a hover state variable and mouseenter & mouseleave events.
  • mouseover event can cause performance issues in deep hierarchies, mouseenter is safer.
  • Use hover state to conditionally apply CSS classes, changing element appearance on hover.
  • Use hover state with v-if to conditionally display elements like tooltips on hover.
  • mouseenter and mouseleave can detect hover on custom Vue components. Use .native modifier in Vue 2.x.

Quickly open Markdown link in new tab (target _blank)

To open a link in a new tab with target _blank in Markdown, use [link](url){:target="_blank"} or create an HTML <a> tag with target="blank".

But for GitHub README files, and on many other platforms that render Markdown, you simply can’t.

You can't open a link in a new tab in the GitHub README file Markdown editor.
You can’t open a link in a new tab in the GitHub README file Markdown editor.

What is Markdown?

Markdown is a lightweight markup language designed for simplicity and readability.

The original goal for Markdown was to enable people to write using an easy-to-read, easy-to-write plain text format, and optionally convert it to structurally valid HTML (or XHTML). In other words, Markdown is a text-to-HTML conversion tool for web writers. Many websites like Github.com, Notion.so, and Medium.com use Markdown in one way or another.

Opening a link in a new tab in Markdown can be beneficial for a number of reasons:

  1. User experience: By opening a link in a new tab, you keep your original page open, allowing the user to easily return to your content after they’ve finished going through the linked content.
  2. Decrease bounce rate: In web analytics, a bounce is when a user lands on your site and then leaves without any other interaction. When your site stays open in one tab while the linked content opens in another, it technically lowers your bounce rate which can be better for site metrics and SEO (Search Engine Optimization).
  3. Preserve context: If your content provides further reading or references via external links, opening these in a new tab helps to maintain the context for the user. The users will not have to go back and forth between pages to understand the context.
  1. Simplicity: Markdown was designed to be as simple as possible, and this does not provide support for attributes in its link syntax. The target="_blank" attribute required to open links in a new tab in HTML is absent from basic Markdown.
  2. Security: Links that open in a new tab can be a vector for a phishing attack known as “tabnapping“. If the linked site is malicious, it can potentially alter the content of the original page and trick users into providing sensitive information.
  3. User control: There’s an argument that it should be up to the user to decide whether they want a link to open in a new window or tab. This can be as simple as Ctrl + Click or a right-click in most browsers.

You can create a link that opens in a new tab in Markdown, create an HTML anchor <a> element, and set it’s target attribute to _blank, link in regular HTML:

Markdown
Visit <a href="https://wp.codingbeautydev.com">Coding Beauty</a> for more educational and interesting content.

Alternatively, create a link that opens in a new tab in Markdown with the [link](url){:target="_blank"} syntax. For example:

Markdown
Visit [Coding Beauty](https://wp.codingbeautydev.com) for articles on JavaScript, React, Next.js, and more.

This works in kramdown syntax and in the Jekyll framework.

Key takeaways

  • To open a link in a new tab in Markdown, use [link](url){:target="_blank"} or an HTML <a> tag with target="blank". However, not all platforms support this.
  • Markdown is a lightweight markup language for creating simple, readable text that can be converted to HTML.
  • Opening links in new tabs can enhance user experience, decrease bounce rates, and preserve context.
  • Many Markdown tools don’t support new tab links due to simplicity, security, and user control concerns.
  • Use an HTML <a> tag or [link](url){:target="_blank"} syntax to open links in new tabs.

One-liners: far more than just one line

Here’s one:

JavaScript
const groupBy = (arr, groupFn) => arr.reduce( (grouped, obj) => ({ ...grouped, [groupFn(obj)]: [...(grouped[groupFn(obj)] || []), obj], }), {} );

and another:

JavaScript
const randomHexColor = () => `#${Math.random().toString(16).slice(2, 8).padEnd(6, '0')}`; console.log(randomHexColor()); // #7a10ba (varies) console.log(randomHexColor()); // #65abdc (varies)

Indeed, they are impressive when done right; a nice way to show off language mastery.

But exactly is a one-liner? Is it really code that takes only one line? If so, then can’t every piece of code qualify as a one-liner, if we just remove all the newline characters? Think about it.

A minified JavaScript file with only one line of code.

It seems like we need a more rigorous definition of what qualifies as a one-liner. And, after a few minutes of thought when writing a previous article on one-liners, I came up with this:

A one-liner is a code solution to a problem, implemented with a single statement in a particular programming language, optionally using only first-party utilities.

Tari Ibaba (😎)

You can clearly see those particular keywords that set this definition apart from others

1. “…single statement…”

Single line or single statement? I go with the later.

Because the thing is, we squeeze every program ever made in a single line of code if we wanted; all the whitespace and file separation is only for us and our fellow developers.

If you’ve used Uglify.js or a similar minifier, you know what it does to all those pitiful lines of code; why it’s called Uglify.

Uglify changes this:

JavaScript
/** Obviously redudant comments here. Just meant to emphasize what Uglify does Class Person */ class Person { /** Constructor */ constructor(name, age) { this.name = name; this.age = age; } /** Print Message */ printMessage() { console.log(`Hello! My name is ${this.name} and I am ${this.age} years old.`); } } /** Creating Object */ var person = new Person('John Doe', 25); /** Printing Message */ person.printMessage();

to this:

JavaScript
class Person{constructor(e,n){this.name=e,this.age=n}printMessage(){console.log(`Hello! My name is ${this.name} and I am ${this.age} years old.`)}}var person=new Person("John Doe",25);person.printMessage();

Would you be impressed by someone who actually wrote code like in this minified way? I would say it’s just badly formatted code.

Would you call this a one-liner?

JavaScript
const sum = (a, b) => { const s1 = a * a; const s2 = b * b; return s1 + s2; }

Tools like the VS Code Prettier extension will easily split up those 3 statements into multiple lines:

The three statements are separated after VS Code Prettier auto-format on save.
The three statements are separated after VS Code Prettier auto-format on save.

A true one-liner way to get the sum of two squares would be something like this:

JavaScript
const sum = (a, b) => a * a + b * b;

One short, succinct statement does the same job with equal clarity.

On the other hand, what about code that spans multiple lines but only uses one statement? Like this:

JavaScript
const capitalizeWithoutSpaces = (str) => str .split('') .filter((char) => char.trim()) .map((char) => char.toUpperCase()) .join('');

I would say this function’s body is far more qualified to be a one-line than the two examples we saw above; single statement.

“…particular programming language”

We need this part because of abstraction.

int sum(int a, int b) { return a * a + b * b; }

This is a one-liner, isn’t it? Very harmless-looking and easy to understand.

How about now? :

sum(int, int): push rbp mov rbp, rsp mov DWORD PTR [rbp-4], edi mov DWORD PTR [rbp-8], esi mov eax, DWORD PTR [rbp-4] imul eax, eax mov edx, eax mov eax, DWORD PTR [rbp-8] imul eax, eax add eax, edx pop rbp ret

Wait, this is just another piece of code, right? Well, it is, except that they do exactly the same thing, but in different languages. One in C++, and the other in Assembly.

Now imagine how much more an equivalent machine language program will have. Clearly, we can only our sum() a one-liner function in the context of C++.

“…using only first-party utilities”

Once again, we need this part because of abstraction.

For us to consider a piece of code as a one-liner, it should only use built-in functions and methods that are part of the language’s standard library or core functionality. For example: array methods, the http module in Node.js, the os module in Python, and so on.

Without this, capitalizeWithoutSpaces() below would easily pass as a JavaScript one-liner:

JavaScript
// Not a one-liner const capitalizeWithoutSpaces = (str) => filter(str.split(''), (char) => char.trim()) .map((char) => char.toUpperCase()) .join(''); function filter(arr, callback) { // Look at all these lines const result = []; for (const item of arr) { if (callback(item)) { result.push(item); } } return result; }

filter could have contained many thousands of lines, yet capitalizeWithoutSpaces would still be given one-liner status.

It’s kind of controversial because a lot of these so-called first-party utilities are abstractions themselves with logic spanning dozens of lines. But just like the “single statement” specifier, it makes it impossible to have an unlimited number of one-liners.

Final thoughts

The essence of a one-liner in programming extends beyond the literal interpretation of its name. It lies not only in the minimalism of physical lines but also in the elegance and sophistication of its execution. It often requires a sound comprehension of the language at hand, an ability to concisely solve a problem, and the art of utilizing the language’s core functionalities with finesse.

A one-liner isn’t merely about squeezing code into a single line; It is where the clarity of thought, the elegance of language mastery, and the succinctness of execution converge. It’s the realm where brevity meets brilliance and the art of coding truly shines.

How to quickly redirect to another page URL in Next.js

To easily redirect to another page URL in Next.js:

  • Static redirect: use the redirects key in next.config.js.
  • In App Router server component: use redirect() from the next/navigation.
  • In pages Router: use useRouter() from next/navigation.
  • In middleware: use NextResponse.redirect() from next/server.
Redirecting to another page or URL in Next.js.
Redirecting to another page URL in Next.js.

To easily redirect to another page URL in Next.js, use the redirects key in your next.config.js file:

next.config.js
// ... const nextConfig = { // ... async redirects() { return [ { source: '/blog', destination: '/', permanent: true, }, ]; }, }; module.exports = nextConfig;

redirects is an async function that returns an array with items that have source, destination, and permanent properties:

  • source: A pattern matching the path of the incoming request.
  • destination: The path you want to redirect to.
  • permanent: If true, Next sets a 308 status code in the redirection response, which tells clients like search engines to cache the redirect from that point onwards. If false, Next will set a 307 status code (temporary redirect) instead, making sure that redirect doesn’t get cached.

Note: While 301 and 302 are the popular status codes for permanent and temporary redirects, Next.js uses 307 and 308 because many browsers changed the request method to GET for the destination URL, regardless of the method the client set in the original request to the source. So if POST v1/posts returned a 302 with v2/posts, the next request to v2/posts may end up GET v2/posts instead of POST v2/posts. But with 307 and 308, the browsers are guaranteed to preserve the request method.

Redirect statically with path parameter to page URL

You can use a path parameter like :path to match any path in the source URL and pass it on to the destination URL.

Here, /news/:slug/ will match /news/codingbeauty and redirect to /blog/codingbeauty.

next.config.js
// ... const nextConfig = { // ... async redirects() { return [ { source: '/news/:slug', destination: '/blog/:slug', permanent: true, }, ]; }, }; module.exports = nextConfig;

It doesn’t work for nested paths though.

Redirect statically with wildcard path to page URL

To match nested routes, query parameters, and anything else in the source path, use the * character after the path parameter.

next.config.js
// ... const nextConfig = { // ... async redirects() { return [ { source: '/articles/:slug*', destination: '/blog/:slug*', permanent: true, }, ]; }, }; module.exports = nextConfig;

Redirect to another page URL dynamically in Next.js App Router server component

To redirect to another page URL dynamically in a Next.js 13 server component, use the redirect() function from the next/navigation module:

JavaScript
import React from 'react'; import { Metadata } from 'next'; import { redirect } from 'next/navigation'; export const metadata: Metadata = { title: 'Next.js - Coding Beauty', description: 'Tutorials by Coding Beauty', }; export default function Page() { if (process.env.NEXT_PUBLIC_HOME) redirect('/home'); return <main>Welcome to Coding Beauty.</main>; }

The redirect() function redirects the browser to another URL; /home in this case.

Here this happens conditionally, but if the redirect is guaranteed to happen, it will surely prevent any JSX in the page from rendering, and editors like VS Code are smart enough to detect this:

Visual Studio Code can detect when the JSX in a page is unreachable due to a redirect.

Redirect to another page URL dynamically in App Router client component

To redirect to another page URL dynamically in a Next.js client component in the Next.js 13 app directory, use the push() method of the object returned by the useRouter hook from the next/navigation module:

Here we’re redirecting from from the /blog path to an external URL:

src/app/blog/page.tsx
'use client'; import React, { useEffect } from 'react'; import { useRouter } from 'next/navigation'; export default function Page() { const router = useRouter(); useEffect(() => { router.push('https://wp.codingbeautydev.com'); }, []); return <main>Welcome to Coding Beauty.</main>; }

The useRouter hook returns a Router object that we use to programmatically change the route, resulting in a client-side redirect.

Redirect to another page URL dynamically in Pages Router component

It’s like in the App router, but useRouter comes from next/router instead of next/navigation.

To redirect to another page URL dynamically in a Next.js client component in the Pages router, use the push() method of the object returned by the useRouter hook from the next/router module.

src/pages/amazing-url.tsx
import Head from 'next/head'; import { useEffect } from 'react'; import { useRouter } from 'next/router'; export default function Home() { const router = useRouter(); useEffect(() => { router.push('/fantastic-url'); }, []); return ( <> <Head> <title>Amazing URL | Coding Beauty</title> <meta name="description" content="Generated by create next app" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.png" /> </Head> <main> <p>Coding Beauty</p> <h2>Amazing URL</h2> </main> </> ); }

The useRouter hook returns a Router object that we use to programmatically change the route to perform a redirect on the client side.

Next.js >= 12: Redirect to another page URL in middleware

To redirect to another page URL using middleware in Next.js 12.1 and above, use the NextResponse.redirect method from the next/server module in a middleware.ts file.

src/middleware.ts
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const url = request.nextUrl.clone(); if (url.pathname === '/old-blog') { url.pathname = '/new-blog'; return NextResponse.redirect(url); } }

Here we use request.nextUrl to get the current URL in the Next.js middleware.

You’ll place middleware.ts file in the same level as your pages directory – which could be the root directory, or src, if enabled.

middleware.ts is at the same level as the pages directory.
middleware.ts is at the same level as the pages directory.

The reason why this only works in Next.js 12.1 above is because starting from Next.js 12.1, relative URLs are not allowed in redirects with NextResponse.redirect() or NextResponse.rewrite().

Next.js 12: Redirect to another page URL in middleware

To redirect to another page URL dynamically using middleware in Next.js 12, use the NextResponse.redirect() method from the next/server module in a _middleware.js file inside the pages folder or a subfolder where you want the middleware to work:

pages/_middleware.js
import { NextResponse, NextRequest } from 'next/server'; export async function middleware(request, event) { const { pathname } = request.nextUrl; if (pathname == '/') { return NextResponse.redirect('/hello-nextjs'); } return NextResponse.next(); }

Key takeaways

  • In Next.js, there are several ways to quickly redirect to another page URL.
  • For static redirects, you can use the redirects key in the next.config.js file. It allows you to define source and destination paths with options for temporary or permanent redirects.
  • Path parameters (e.g., /blog/:slug) and wildcard paths (e.g., /blog/:slug*) can be used to match and redirect nested routes or query parameters.
  • In a Next.js App Router server component, you can use the redirect() function from the next/navigation module to dynamically redirect to another URL.
  • In the Next.js client component, you can use the push() method from the useRouter hook in the next/navigation (Next.js 13) or next/router (Next.js 12 and below) module to programmatically change the route and perform a client-side redirect.
  • For middleware in Next.js 12.1 and above, you can use the NextResponse.redirect() method from the next/server module in a middleware.ts file.
  • In Next.js 12 middleware, you can use the NextResponse.redirect() method in a _middleware.js file inside the pages folder or a subfolder.

Mojo: 7 brilliant Python upgrades in the new AI language

It is 35,000 times faster than Python. It is quicker than C. It is as easy as Python.

Enter Mojo: a newly released programming language made for AI developers and made by Modular, a company founded by Chris Lattner, the original creator of Swift.

This 35000x claim came from a benchmark comparison between Mojo and other languages, using the Mandelbrot algorithm on a particular AWS instance.
This 35000x claim came from a benchmark comparison between Mojo and other languages, using the Mandelbrot algorithm on a particular AWS instance.

It’s a superset of Python, combining Python’s usability, simplicity, and versatility with C’s incredible performance.

If you’re passionate about AI and already have a grasp on Python, then Mojo is definitely worth a try. So, let’s dive in and explore 7 powerful features of this exciting language together.

Mojo’s features

I signed up for Mojo access shortly after it was announced and got access a few days later.

I got access to the Mojo playground.

I started exploring all the cool new features they had to offer and even had the chance to run some code and see the language in action. Here are 7 interesting Python upgrades I found:

1. let and var declarations

Mojo introduces new let and var statements that let us create variables.

If we like we can specify a type like Int or String for the variable, as we do in TypeScript. var allows variables to change; let doesn’t. So it’s not like JavaScript’s let and var – There’s no hoisting for var and let is constant.

Mojo
def your_function(a, b): let c = a # Uncomment to see an error: # c = b # error: c is immutable if c != b: let d = b print(d) your_function(2, 3)

2. structs for faster abstraction

We have them in C++, Go, and more.

Structs are a Mojo feature similar to Python classes, but they’re different because Mojo classes are static: you can’t add more methods are runtime. This is a trade-off, as it’s less flexible, but faster.

Mojo
struct MyPair: var first: Int var second: Int # We use 'fn' instead of 'def' here - we'll explain that soon fn __init__(inout self, first: Int, second: Int): self.first = first self.second = second fn __lt__(self, rhs: MyPair) -> Bool: return self.first < rhs.first or (self.first == rhs.first and self.second < rhs.second)

Here’s one way struct is stricter than class: all fields must be explicitly defined:

Fields must be explicitly defined in Mojo structs.

3. Strong type checking

These structs don’t just give us flexibility, they let us check variable types at compile-time in Mojo, like the TypeScript compiler does.

Mojo
def pairTest() -> Bool: let p = MyPair(1, 2) # Uncomment to see an error: # return p < 4 # gives a compile time error return True

The 4 is an Int, the p is a MyPair; Mojo simply can’t allow this comparison.

4. Method overloading

C++, Java, Swift, etc. have these.

Function overloading is when there are multiple functions with the same name that accept parameters with different data types.

Look at this:

Mojo
struct Complex: var re: F32 var im: F32 fn __init__(inout self, x: F32): """Makes a complex number from a real number.""" self.re = x self.im = 0.0 fn __init__(inout self, r: F32, i: F32): """Makes a complex number from its real and imaginary parts.""" self.re = r self.im = i

Typeless languages like JavaScript and Python simply can’t have function overloads, for obvious reasons.

Although overloading is allowed in module/file functions and class methods based on parameter/type, it won’t work based on return type alone, and your function arguments need to have types. If don’t do this, overloading won’t work; all that’ll happen is the most recently defined function will overwrite all those previously defined functions with the same name.

5. Easy integration with Python modules

Having seamless Python support is Mojo’s biggest selling point by far.

And using Python modules in Mojo is straightforward. As a superset, all you need to do is call the Python.import_module() method, with the module name.

Here I’m importing numpy, one of the most popular Python libraries in the world.

Mojo
from PythonInterface import Python # Think of this as `import numpy as np` in Python let np = Python.import_module("numpy") # Now it's like you're using numpy in Python array = np.array([1, 2, 3]) print(array)

You can do the same for any Python module; the one limitation is that you have to import the whole module to access individual members.

All the Python modules will run 35,000 times faster in Mojo.

6. fn definitions

fn is basically def with stricter rules.

def is flexible, mutable, Python-friendly; fn is constant, stable, and Python-enriching. It’s like JavaScript’s strict mode, but just for def.

Mojo
struct MyPair: fn __init__(inout self, first: Int, second: Int): self.first = first self.second = second

fn‘s rules:

  • Immutable arguments: Arguments are immutable by default – including self – so you can’t mistakenly mutate them.
  • Required argument types: You have to specify types for its arguments.
  • Required variable declarations: You must declare local variables in the fn before using them (with let and var of course).
  • Explicit exception declaration: If the fn throws exceptions, you must explicitly indicate so – like we do in Java with the throws keyword.

7. Mutable and immutable function arguments

Pass-by-value vs pass-by-reference.

You may have across this concept in languages like C++.

Python’s def function uses pass-by-reference, just like in JavaScript; you can mutate objects passed as arguments inside the def. But Mojo’s def uses pass-by-value, so what you get inside a def is a copy of the passed object. So you can mutate that copy all you want; the changes won’t affect the main object.

Pass-by-reference improves memory efficiency as we don’t have to make a copy of the object for the function.

But what about the new fn function? Like Python’s def, it uses pass-by-reference by default, but a key difference is that those references are immutable. So we can read the original object in the function, but we can’t mutate it.

Immutable arguments

borrowed a fresh, new, redundant keyword in Mojo.

Because what borrowed does is to make arguments in a Mojo fn function immutable – which they are by default. This is invaluable when dealing with objects that take up a substantial amount of memory, or we’re not allowed to make a copy of the object we’re passing.

For example:

Mojo
fn use_something_big(borrowed a: SomethingBig, b: SomethingBig): """'a' and 'b' are both immutable, because 'borrowed' is the default.""" a.print_id() // 10 b.print_id() // 20 let a = SomethingBig(10) let b = SomethingBig(20) use_something_big(a, b)

Instead of making a copy of the huge SomethingBig object in the fn function, we simply pass a reference as an immutable argument.

Mutable arguments

If we want mutable arguments instead, we’ll use the new inout keyword instead:

Mojo
struct Car: var id_number: Int var color: String fn __init__(inout self, id: Int): self.id_number = id self.color = 'none' # self is passed by-reference for mutation as described above. fn set_color(inout self, color: String): self.color = color # Arguments like self are passed as borrowed by default. fn print_id(self): # Same as: fn print_id(borrowed self): print('Id: {0}, color: {1}') car = Car(11) car.set_color('red') # No error

self is immutable in fn functions, so we here we needed inout to modify the color field in set_color.

Key takeaways

  • Mojo: is a new AI programming language that has the speed of C, and the simplicity of Python.
  • let and var declarations: Mojo introduces let and var statements for creating optionally typed variables. var variables are mutable, let variables are not.
  • Structs: Mojo features static structs, similar to Python classes but faster due to their immutability.
  • Strong type checking: Mojo supports compile-time type checking, akin to TypeScript.
  • Method overloading: Mojo allows function overloading, where functions with the same name can accept different data types.
  • Python module integration: Mojo offers seamless Python support, running Python modules significantly faster.
  • fn definitions: The fn keyword in Mojo is a stricter version of Python’s def, requiring immutable arguments and explicit exception declaration.
  • Mutable and immutable arguments: Mojo introduces mutable (inout) and immutable (borrowed) function arguments.

Final thoughts

As we witness the unveiling of Mojo, it’s intriguing to think how this new AI-focused language might revolutionize the programming realm. Bridging the performance gap with the ease-of-use Python offers, and introducing powerful features like strong type checking, might herald a new era in AI development. Let’s embrace this shift with curiosity and eagerness to exploit the full potential of Mojo.

Why “Yarn 2” is actually Yarn 3

What do we know as Yarn 2?

It’s the modern version of Yarn that comes with important upgrades to the package manager including PNMP-style symlinks, and an innovative new Plug ‘n’ Play module installation method for much-reduced project sizes and rapid installations.

But after migrating from Yarn 1, you’ll find something interesting, as I did – the thing widely known as Yarn 2 is actually… version 3?

After migrating to "Yarn 2" and checking the version, it was shown to be version 3.

Why is “Yarn 2” using version 3?

It’s because Yarn 1 served as the initial codebase which was completely overhauled in the Yarn v2.0 (the actual version 2), enhancing its efficiency and effectiveness, with its launch taking place in January 2020. As time moved on, the introduction of a fresh major, Yarn v3.0, happened, thankfully without the need for another codebase rewrite. The upcoming major update is expected to be Yarn v4.0, and so on.

Despite the historical tendency of releasing few major updates, there was a growing trend among some individuals to label everything that used the new codebase as “Yarn 2”, which includes Yarn 2.x versions and future ones such as 3.x. This, however, was a misinterpretation as “Yarn 2” strictly refers to the 2.x versions. A more accurate way to reference the new codebase would be “Yarn 2+” or “Yarn Berry” – a codename that the team selected for the new codebase when they started developing it.

As once stated by one of the maintainers in a related GitHub discussion:

Some people have started to colloquially call “Yarn 2” everything using this new codebase, so Yarn 2.x and beyond (including 3.x). This is incorrect though (“Yarn 2” is really just 2.x), and a better term to refer to the new codebase would be Yarn 2+, or Yarn Berry (which is the codename I picked for the new codebase when I started working on it).

arcanis, a Yarn maintainer

How to migrate from Yarn v1 to Yarn Berry

A Yarn Berry installation in progress.
A Yarn Berry installation in progress.

If you’re still using Yarn version 1 – or worse, NPM – you’re missing out.

The new Yarn is loaded with a sizable number of upgrades that will significantly improve your developer experience when you start using it. These range from notable improvements in stability, flexibility, and extensibility, to brand new features, like Constraints.

You can migrate from Yarn v1 to Yarn Berry in 7 easy steps:

  1. Make sure you’re using Node version 18+.
  2. Run corepack enable to activate Corepack.
  3. Navigate to your project directory.
  4. Run yarn set version berry.
  5. Convert your .npmrc and .yarnrc files into .yarnrc.yml (as explained here).
  6. Run yarn install to migrate the lockfile.
  7. Commit all changes.

In case you experience any issues due to breaking changes, this official Yarn Berry migration guide should help.

Final thoughts

The Yarn versioning saga teaches us an important lesson: terminology matters.

What many of us dub as “Yarn 2” is actually “Yarn 2+” or “Yarn Berry”, the game-changing codebase. This misnomer emphasizes our need to stay current, not just with evolving tools and features, but with their rightful names as well. After all, how we understand and converse about these improvements shapes our effectiveness and fluency as developers.

How to quickly get the height or width of an element in React

To get the height or width of an element in React, use the useRef, useEffect, and useState hooks to access the element’s offsetWidth or offsetHeight property:

JavaScript
import React, { useEffect, useState, useRef } from 'react'; function ExampleComponent() { const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); const elementRef = useRef(null); useEffect(() => { setWidth(elementRef.current.offsetWidth); setHeight(elementRef.current.offsetHeight); }, []); return ( <div ref={elementRef} style={{ width: '50%', height: '50%', border: '1px solid black' }} > <p>Coding Beauty</p> <p>{`Element size: (${width}, ${height})`}</p> </div> ); } export default function App() { return ( <div> <ExampleComponent /> </div> ); }
The height and width of the element is displayed with React.

useEffect() runs after the component mounts or re-renders, but useLayoutEffect() runs before. They both have a dependency array that triggers them when any of those dependencies change.

We create a ref for the target element with useRef(), and assign it to its ref prop, so we can access the HTMLElement object for this React element.

useRef returns a mutable ref object that doesn’t change its value when a component is updated. Also, modifying the value of this object’s current property does not cause a re-render. This is in contrast to the setState update function returned from useState.

We use useState() to create a state that we update when useEffect() gets called. This update makes the element’s width and height display on the page.

Get height and width of element with clientHeight and clientWidth

You can also get an element’s height and width in React with clientHeight and clientWidth. Unlike offsetWidth, it includes padding but excludes borders and scrollbars.

JavaScript
import React, { useRef, useState, useEffect } from 'react'; function ExampleComponent() { const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); const elementRef = useRef(null); useEffect(() => { setWidth(elementRef.current.clientWidth); setHeight(elementRef.current.clientHeight); }, []); return ( <div ref={elementRef} style={{ width: '50%', height: '50%' }}> <p>Coding Beauty</p> <p> <b>{`Element size: (${width}, ${height})`}</b> </p> </div> ); } export default function App() { return ( <div> <ExampleComponent /> </div> ); }
Getting the size of an element in React with clientWidth and clientHeight.

Get height and width of element dynamically

You can get the height and width of an element dynamically, which means the height and width updates on window resize.

We do this with a resize event listener:

JavaScript
import React, { useEffect, useState, useRef } from 'react'; function ExampleComponent() { const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); const elementRef = useRef(null); useEffect(() => { const handleResize = () => { setWidth(elementRef.current.offsetWidth); setHeight(elementRef.current.offsetHeight); }; handleResize(); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); return ( <div ref={elementRef} style={{ width: '50%', height: '50%' }}> <p>Getting element width dynamically</p> <p><b>{`Element size: (${width}, ${height})`}</b></p> </div> ); } export default function App() { return ( <div> <ExampleComponent /> </div> ); }

We call addEventListener() in useEffect() to set the resize event listener on the element before it renders on the screen.

The resize event listener is called whenever the user resizes the window. In the listener, we update the state that stores the element’s width and height, and this causes a re-render.

We call removeEventListener() in useEffect‘s clean-up function to stop listening for resize events when the component is unmounted or when the dependencies change to prevent memory leaks and unintended side effects.

Get element height and width before render in React

To get the width and height of an element before render in React, we can combine two React hooks: useRef and useLayoutEffect.

JavaScript
import React, { useRef, useLayoutEffect, useState } from 'react'; function ExampleComponent() { const [width, setWidth] = useState(0); const [height, setHeight] = useState(0); const elementRef = useRef(null); useLayoutEffect(() => { setWidth(elementRef.current.offsetWidth); setHeight(elementRef.current.offsetHeight); }, []); return ( <div style={{ width: '50%', height: '50%' }}> <p>Coding Beauty</p> <div ref={elementRef}> Element size: ({width}, {height}) </div> </div> ); } export default function App() { return ( <div> <ExampleComponent /> </div> ); }

So the difference between “before render” and “after render” is useLayoutEffect() and useEffect().

useLayoutEffect() works just like useEffect(), but the key difference is that it fires before the browser repaints the screen – before React renders the component.

We pass an empty dependencies array to useLayoutEffect() to make sure it only gets called once.

Here we create a ref for the target element with useRef(), and assign it to its ref prop, so we can access the HTMLElement object for this React element.

useRef returns a mutable ref object that doesn’t change its value when a component is updated. Also, modifying the value of this object’s current property does not cause a re-render. This is in contrast to the setState update function returned from useState.

We do use useState() though, to create a state that we update when useLayoutEffect() gets called. So calling setWidth() will cause the component to be re-rendered.

To get the actual width and height, we use the offsetWidth and offsetHeight properties, which include borders, padding, and any scrollbars.

Key takeaways

  1. To get the height or width of an element in React, combine the useRef, useEffect, and useState hooks to get the value of offsetWidth and offsetHeight.
  2. clientWidth and clientHeight are similar to offsetWidth and offsetHeight, but they include padding and exclude borders and scrollbars.
  3. To get the dimensions of the element dynamically, create a window resize event listener to automatically update the size when the user resizes the browser window.
  4. To get the size of the element before render, replace useEffect with useLayoutEffect.

[SOLVED] 0308010C:digital envelope routines::unsupported

The error:0308010C:digital envelope routines::unsupported error happens in Node.js when a JavaScript module still uses a flawed OpenSSL version that is incompatible with the version Node.js uses.

The "error:0308010C:digital envelope routines::unsupported" error occurring in Vue.js.
The error:0308010C:digital envelope routines::unsupported error occurring.

To fix it, downgrade to Node.js v16.13.0, or use the npm audit fix --force command to upgrade your packages to versions that use the updated OpenSSL version.

Why does the error:0308010C:digital envelope routines::unsupported error occur in Node.js?

In Node.js v17, the Node.js team patched an OpenSSL security vulnerability. This fix introduced a breaking change; if you try to use OpenSSL in Node.js v17 or later versions without also updating those modules that use previous OpenSSL versions, you’ll get this error.

And you’ll get it the next time Node.js is updated to use a newer OpenSSL version with breaking changes and you haven’t updated the OpenSSL-dependent libraries.

Fix: Upgrade NPM packages

To fix the error:0308010C:digital envelope routines::unsupported error, update the Node.js packages causing the error to the latest version.

Run npm audit fix to fix vulnerabilities

You can run the npm audit fix command to identify those packages using the outdated OpenSSL version and fix them automatically.

Shell
npm audit fix

npm audit fix reviews the project’s dependency tree to identify packages that have known vulnerabilities, and attempts to upgrade and/or fix the vulnerable dependencies to a safe version.

npm audit fix --force

If you want to install semver major updates to vulnerable packages, you can use the --force option. 

Shell
npm audit fix --force

Be cautious with this option: it could potentially break your project.

yarn-audit-fix

If you’re a Yarn user, you can use the yarn-audit-fix package to do what npm audit fix does.

Upgrade Webpack to v5

If you’re using Webpack directly to bundle your files, you can upgrade it to version v5 – specifically, v5.61.0 – to fix the error:0308010C:digital envelope routines::unsupported error.

Shell
npm i webpack@latest # Yarn yarn add webpack@latest

If instead, you’re using a tool like Create React App and the Vue CLI that uses Webpack internally, you’ll upgrade the tool to a version that doesn’t have this error.

Fix for Create React App: Upgrade react-scripts to v5

If you’re using Create React App then you can fix the error:0308010C:digital envelope routines::unsupported error by upgrading react-scripts to version 5, which comes with the newer Webpack version 5.

Install version 5 or later with this command:

Shell
npm i react-scripts@latest # Yarn yarn add react-scripts@latest

Fix for Vue CLI: Upgrade to v5

Similarly for the Vue CLI, you can fix the error:0308010C:digital envelope routines::unsupported error by upgrading the Vue CLI to version 5 which also comes with the newer Webpack version 5.

Install Vue CLI version 5 or later with this command:

Shell
npm update -g @vue/cli # OR yarn global upgrade --latest @vue/cli

More info on how to upgrade the Vue CLI here.

Fix: Use --openssl-legacy-provider option

To fix the error:0308010C:digital envelope routines::unsupported error in Node.js, you can also use the --openssl-legacy-provider option when running the script.

This solution is more of a hack though: it leaves your app open to security threats.

The --openssl-legacy-provider option is only available in Node version 17 or later.

Run with script

So for the start script, you’ll use this command:

Shell
export NODE_OPTIONS=--openssl-legacy-provider && npm run start # Windows set NODE_OPTIONS=--openssl-legacy-provider && npm run start

Modify script

You can also set this directly in the script to avoid needless repetition.

On Linux/Mac:

JSON
{ ... "scripts": { "start": "export NODE_OPTIONS=--openssl-legacy-provider && webpack serve", "build": "webpack --mode production" } ... }

On Windows:

JSON
{ ... "scripts": { "start": "set NODE_OPTIONS=--openssl-legacy-provider && node .", "build": "set NODE_OPTIONS=--openssl-legacy-provider && node build.js" } ... }

Make sure the script is cross-platform

But now the scripts aren’t cross-platform.

They’ll obviously be problematic when collaborating and team members use other operating systems. What do we do? We install the cross-env NPM module and run the script with it.

Shell
npm i cross-env # Yarn yarn add cross-env
JSON
{ ... "scripts": { "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack .", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider node build.js" }, "devDependencies": { "cross-env": "^7.0.3" } ... }

Now the script runs successfully on every platform.

Fix for Vue CLI

So to fix the error:0308010C:digital envelope routines::unsupported error when using Vue with the Vue CLI, install the cross-env module and set the --openssl-legacy-provider option:

JSON
{ ... "scripts": { "serve": "cross-env NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve", ... }, "devDependencies": { "cross-env": "^7.0.3" ... } ... }

Fix for Create React App

And to fix the error:0308010C:digital envelope routines::unsupported error when using React with Create React App, install the cross-env module and set the --openssl-legacy-provider option.

JSON
{ ... "scripts": { "serve": "cross-env NODE_OPTIONS=--openssl-legacy-provider ", ... }, "devDependencies": { "cross-env": "^7.0.3" ... } ... }

Fix: Downgrade to Node.js v16.13.0

To fix the error:0308010C:digital envelope routines::unsupported error in Node.js, downgrade your Node.js version to 16.13.0.

This solution is more of a hack though, as it leaves your app open to security threats.

Install from the official website

Use this official link to download Node.js v16.13.0.

Install with Chocolatey

If you’re using Chocolatey, Node.js is available as the nodejs package, meaning you can easily install it in a terminal using the following command.

Shell
# Use current LTS version choco install nodejs --version=18.5.0

Install with nvm

If you’re using nvm or nvm-windows, use these commands to quickly install and switch to Node.js v16.13.0.

Shell
nvm install 16.13.0 nvm use 16.13.0

How to Quickly Reveal the Current File in Explorer in VS Code

You either want to reveal the current file in the VS Code Explorer sidebar view or in your OS file manager. We cover both in this article.

Reveal current file in Explorer view in VS Code

To reveal the current file in the Explorer view of Visual Studio Code, use the Reveal Active File in Explorer View command, accessible from the Command Palette.

Revealing the active file in the VS Code Explorer view.

Why is it useful to reveal the current file in the VS Code Explorer view?

When working on a project with numerous files and directories, it can sometimes be challenging to remember the exact location of a specific file. Revealing the current file in the VS Code Explorer view allows you to quickly locate the file’s position within the project structure.

  1. Context: This is particularly useful when you want to gain a broader context of where the file is located in relation to other files and folders.
  2. Navigation: And you can easily navigate to these related files.
  3. File management: VS Code’s Explorer view provides file management capabilities, such as renaming, moving, and deleting files. If you’re currently editing a file and you want to perform a management action on it, revealing the file in the Explorer view makes it easier to perform these actions without having to manually navigate through the directory structure.
  4. Version control: If your project is under version control like Git, revealing the current file in the Explorer view can help you understand the file’s status in the context of version control. You can see if the file has been modified, staged, or is part of a particular branch, which can aid in your development workflow.
  5. Collaboration: When working on a project with others, revealing the current file can help your team members easily find and access the same file you’re working on. This is especially useful if you’re discussing a specific file in a conversation or during a code review.

Use the Reveal in File Explorer View command

To reveal the current file in the Explorer view in VS Code, run the Reveal Active File in Explorer View command.

Reveal the active file in the VS Code Explorer view.

In VS Code, we have commands – defined actions that carry our various operations in the editor.

We can easily run a command with the Command Palette, which we can access with these keyboard shortcuts:

  • Windows / LinuxCtrl + Shit + P
  • Mac: Command + Shift + P

Reveal current file in Explorer with active editor context menu

You can also reveal the current file in the VS Code Explorer sidebar with the Reveal in Explorer View option in the context menu that shows up when you right-click the filename at the top.

Reveal the current file with the VS Code active editor context menu.

This item is also there in the context menu that shows when you right-click the file in the Source Control view.

This Reveal in Explorer View item is in the Source Control view context menu.

Reveal current file in Windows File Explorer / Mac Finder

To reveal the current file in your operating system’s file manager, use the Reveal in File Explorer command, accessible from the Command Palette.

The Reveal in File Explorer command in VS Code.

By the way, if you’re on Windows 11 and you’re dealing with File Explorer clutter, this tiny utility called WinENFET can help, by automatically opening File Explorer in a new tab, instead of a new window.

Why is it useful to reveal the current file in File Explorer/Finder?

When managing a project that includes many files and folders, it can occasionally become difficult to recall the precise location of a particular file. By displaying the current file in your operating system’s file manager, you can swiftly identify the file’s place within the project hierarchy.

This is useful for several reasons:

  1. Context: Helps you understand and navigate your project’s larger file hierarchy. This is especially helpful in large projects with complex file structures.
  2. External operations: You can perform actions not available in VS Code, like viewing file properties (creation date, size, etc.) or file permissions.
  3. Data transfer: Allows you to quickly locate the path for file transfers. If you need to send the file as an email attachment or upload it to a server, you can quickly find it in the operating system’s file manager.
  4. Easy access: If you’re working with a file in VS Code and you want to quickly open it in another application, revealing the file in the file manager makes this easy.
  5. Collaboration: If you’re working with a team, it’s easy to reveal the file in the file manager, zip it, and send it to team members as needed.

Use the Reveal in File Explorer command

To reveal the current file in your OS’s file manager in VS Code, run the Reveal in File Explorer command.

The Reveal in File Explorer command in VS Code.

In VS Code, we have commands: defined actions that carry out various operations in the editor.

We can easily run a command with the Command Palette, which we can access with these keyboard shortcuts:

  • Windows / Linux: Ctrl + Shit + P
  • Mac: Command + Shift + P

Reveal current file in File Explorer with active editor context menu

Alternatively, you can reveal the current file in your OS’s file manager with the Reveal in File Explorer option in the context menu that shows up when you right-click the filename at the top.

Revealing the current file in File Explorer/Finder from VS Code.

Set custom keyboard shortcuts for commands in VS Code

To set a custom keyboard shortcut for the Reveal in File Explorer or Reveal Active File in Explorer View command, change the keybinding for the command in the Keyboard Shortcuts page.

To get this page, you can click the Keyboard Shortcuts item on the Manage popup shown below or use the shortcut next to the text (Ctrl + K, Ctrl + S here).

Opening the Keyboard Shortcuts page from the Manage popup in VS Code.

Once you get there, search for the Reveal in File Explorer or Reveal Active File in Explorer View command in the search bar.

Searching for the Reveal in File Explorer keyboard shortcut.

Then double-click the command, type a new keyboard shortcut, and press the Enter key to carry out the change.

Changing the Reveal in File Explorer keyboard shortcut in VS Code.

Key takeaways

  • To reveal a file in the VS Code Explorer view, run the Reveal Active File in Explorer View command. You can do this with the Command Palette, or by setting a custom keyboard shortcut.
  • To reveal a file in your OS file manager (Windows File Explorer, Mac Finder, etc.), run the Reveal in File Explorer command. You can also do this with the Command Palette, or by setting a custom keyboard shortcut.
  • To set a keyboard shortcut for a command in VS Code, open the Keyboard Shortcuts page, select the command, type the new short, and confirm with Enter.

How to quickly get the union of two Sets in JavaScript

To get the union of two Sets in JavaScript, convert the sets to arrays and merge them, then create a Set from the merged array, i.e., new Set([...set1, ...set2]).

For example:

JavaScript
function getUnion(set1, set2) { return new Set([...arr1, ...arr2]); } const set1 = new Set([1, 2, 3, 4]); const set2 = new Set([3, 4, 5, 6]); const union = getUnion(set1, set2); console.log(union); // Set(6) { 1, 2, 3, 4, 5, 6 }

Set() constructor

The Set() constructor creates a new Set object from an iterable like an array. As a Set can only contain unique values, it removes any possible duplicates that may be in the array it receives.

JavaScript
const set = new Set([1, 1, 2, 3, 3, 4]); console.log(set); // Set(4) [1, 2, 3, 4]

Spread syntax (...)

The array we pass to Set() is a merge of two arrays that represent the two Sets. The spread syntax (...) unpacks the value of each Set into the array.

JavaScript
const array1 = [10, 20, 30]; const array2 = [40, 50, 60]; const mergedArray = [...array1, ...array2]; console.log(mergedArray);

Use Array concat() to merge arrays

If you like, you can use the Array concat() method to join the arrays. Here the spread syntax only converts the Sets to arrays.

JavaScript
function getUnion(set1, set2) { // Using Array concat() in place of spread syntax return new Set([...set1].concat([...set2])); } const set1 = new Set([1, 2, 3, 4]); const set2 = new Set([3, 4, 5, 6]); const union = getUnion(set1, set2); console.log(union); // Set(6) { 1, 2, 3, 4, 5, 6 }

Use Array from() to convert Set to array

You can use the Array from() method in place of the spread syntax (...) to convert the Sets to arrays before merging them:

JavaScript
function getUnion(set1, set2) { // Using Array concat() in place of spread syntax return new Set(Array.from(set1).concat(Array.from(arr2)); } const set1 = new Set([1, 2, 3, 4]); const set2 = new Set([3, 4, 5, 6]); const union = getUnion(set1, set2); console.log(union); // Set(6) { 1, 2, 3, 4, 5, 6 }

We can use a similar approach to easily get the union of two arrays in JavaScript.

Get union of two arrays in JavaScript

To get the union of two arrays in JavaScript, merge the arrays, create a new Set object from the merged result to remove the duplicates, then convert it back to an array, i.e., Array.from(new Set([...arr1, ...arr2])).

For example:

JavaScript
function getUnion(arr1, arr2) { return Array.from(new Set([...arr1, ...arr2])); } const array1 = [1, 2, 3, 4, 5]; const array2 = [4, 5, 6, 7, 8]; const union = getUnion(array1, array2); // [1, 2, 3, 4, 5, 6, 7, 8] console.log(union);

Key takeaways

  • To get the union of two Sets in JavaScript, convert the Sets to arrays, merge them, and convert the merged array back to a Set object, i.e., new Set([...set1, ...set2]).
  • You can get the union of two arrays in JavaScript in a similar way, i.e., [...new Set([...arr1, ...arr2])].