To allow Next.js to display images from all domains, modify your next.config.js file to add an object with protocol and hostname properties to the remotePatterns array property.
Or you can modify your next.config.js to include codingbeautydev.com:
Of course, if you don’t have any domains property, you just create one with the new domain as its single element.
While the image.domains is simple and straightforward, the remotePatterns property gives us more flexibility with its support for wildcard pattern matching, and protocol, port, and pathname restriction.
These advanced restrictions remotePatterns provide greater security when you don’t own all the content in the domain, which is why the Next.js team recommends it.
Why do we need to be explicit with domains for Next.js images?
So whether you use remotePatterns or images.domains, you still need to be explicit about the domains that a next/image component can display.
By doing so, you can prevent the potential security risks of loading images from random, unverified URLs that could contain malicious code.
To get the intersection of two Sets in JavaScript, combine the filter() and has() array methods:
JavaScriptCopied!
const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5, 6, 7, 8]);
const intersection = new Set([...set1].filter(x => set2.has(x)));
console.log(intersection); // Set {4, 5}
The Arrayfilter() method tests each element in an array against a condition specified by a callback function and creates a new array filled with elements that pass the test. It doesn’t modify the original array.
Anywhere you see the forEach(), you can use the for..of loop in its place:
JavaScriptCopied!
const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5, 6, 7, 8]);
const intersection = new Set();
for (const value of set1) {
if (set2.has(value)) {
intersection.add(value);
}
}
console.log(intersection); // Set {4, 5}
Get intersection of two Sets with reduce() method
You can also use the reduce() method to get the intersection of two Set objects in JavaScript:
JavaScriptCopied!
const set1 = new Set([1, 2, 3, 4, 5]);
const set2 = new Set([4, 5, 6, 7, 8]);
const intersection = [...set1].reduce((acc, value) => {
if (set2.has(value)) {
acc.add(value);
}
return acc;
}, new Set());
console.log(intersection); // Set {4, 5}
The reduce() method calls a function on each element of an array to accumulate a resulting value:
To enable or disable autosave in VS Code, use the File > Auto Save option from the menu bar.
After this, the “dirty” indicator will no longer show up when you modify a saved file.
Before:
After:
Why do we need autosave?
So we can stop mindlessly pressing Ctrl + S.
So we can save time, increase productivity, and be much more certain that we’re working with the latest changes.
Autosave is not perfect though; it’s up to you to weigh the pros and cons – which we comprehensively cover here.
What’s not to like about autosave?
Some of the cons we talk about in that autosave article:
It wastes resources because it saves even when you’re not ready to view the results of your changes.
It makes it harder to recover from unexpected errors, for example, making a buggy file change and accidentally closing the file.
There’s no auto-formatting with auto-save.
Enable/disable autosave in VS Code Settings
Alternatively, we can disable autosave in Visual Studio Code using the Files: Auto Save setting in the Settings page.
You can easily navigate to this page with the gear icon at the top-left of the code editor:
Once you get there, you can use the search bar to find the setting.
As you can see, Files: Auto Save can be one of four possible values, namely:
off – self-explanatory: disable autosave.
afterDelay: – the new value enables autosave with the File > Auto Save setting. autosaves the file sometime after your changes.
onFocusDelay – autosaves the dirty file when you switch windows or tabs.
onWindowChange – as the name implies, autosaves the unsaved file when you switch windows in the operating system.
So there are more customization options in the Settings page than in the menu bar.
Change autosave delay in VS Code
When Files: Auto Save is set to afterDelay, you can modify the autosave delay in Visual Studio Code with the Files: Auto Save Delay setting.
You may be better off increasing the autosave delay instead of disabling autosave entirely, so VS Code still saves your work automatically, while minimizing the impact on system resources.
Enable/disable autosave in VS Code with Command Palette
To turn autosave on or off in Visual Studio Code, you can also use the File: Toggle Auto Save command, accessible from the Command Palette:
By Tari Ibaba
/ Last updated on September 30, 2023
To detect a route change in Next.js:
app directory: use useEffect and usePathname.
pages directory: use useEffect and useRouter.
Listen for route/page change in Next.js app directory
To listen for a route change in Next.js 13 app directory, use the useEffect and the usePathname hooks. The action in useEffect will run anytime the pathname from usePathname changes.
Here we log to the console and change the state of the component when the route changes.
Page change listener must persist with client-side routing
For this detection to work, the component containing this useEffect needs to be somewhere in the DOM where it will not get unmounted with client-side navigation.
In the Next.js 13 app directory, this could be the layout.tsx file:
src/app/layout.tsxCopied!
import { Metadata } from 'next';
import '@/styles/globals.css';
import { RouteChangeListener } from './route-change-listener';
export const metadata: Metadata = {
title: 'Coding Beauty',
description: 'The official Coding Beauty home page.',
icons: {
icon: '/favicon.png',
},
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
{/* 👇 Persists with client-side navigation */}
<RouteChangeListener />
<body>{children}</body>
</html>
);
}
useEffect needs 'use client'
Also, since server components are the default in Next.js 13, you’ll need to add the 'use client' directive at the top of the component file.
Otherwise, you won’t be able to use interactive client-side features like React hooks, including useEffect.
Listen for route/page change in Next.js pages directory
To handle a URL or location change in Next.js pages directory, combine the useEffect and the useRouter hooks:
src/pages/url-change-listener.tsxCopied!
import { useEffect } from 'react';
import { useRouter } from 'next/router';
export function UrlChangeListener() {
const router = useRouter();
useEffect(() => {
console.log(`The page is now: ${router.pathname}`);
}, [router]);
return <></>;
}
Route change detector must persist with client-side routing
Just like with the app directory, the component that listens for the URL change with useEffect needs to be somewhere in the DOM where it will not get unmounted with client-side navigation.
In the pages directory, this could be the _app.tsx or _app.js file:
src/pages/_app.tsxCopied!
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import { UrlChangeListener } from './url-change-listener';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<UrlChangeListener />
<Component {...pageProps} />
</>
);
}
Detect route/page with useRouter() events
Alternatively, we can detect a client-side URL change in the Next.js pages directory with events that the useRouter() object emits. For example:
src/pages/url-change-listener.tsxCopied!
import { useEffect } from 'react';
import { useRouter } from 'next/router';
export function UrlChangeListener() {
const router = useRouter();
useEffect(() => {
const startHandler = () => {
console.log('Router change started');
};
const completeHandler = () => {
console.log('Router change completed');
};
router.events.on('routeChangeStart', startHandler);
router.events.on('routeChangeComplete', completeHandler);
return () => {
router.events.off('routeChangeStart', startHandler);
router.events.off('routeChangeComplete', completeHandler);
};
}, []);
// 👇 You can put a progress bar or something here
return <></>;
}
Here we used two important router events:
routeChangeStart – fires when the route is about to change.
routerChangeComplete – fires when the router has changed completely.
There’s more too, and their names are just as self-explanatory as these two.
Key takeaways
To listen for a route or page change in Next.js app directory, combine the useEffect and usePathname hooks.
Detect a URL change in the pages directory with the useEffect and useRouter hooks.
You can also use the routeChangeStart and routeChangeComplete events from the useRouter() object to handle a location change.
The “Cannot read property ‘then’ of undefined” error occurs in JavaScript when you call try then() on a value – typically a function’s return value – but this value is undefined.
This could happen for one of the following reasons:
Not returning the Promise in the function with return.
Not returning a value in an async function.
Not chaining Promises properly.
To fix it, ensure the function returns actually returns a Promise.
Now let’s look at some specific cases of the error and learn how to fix it in a few easy steps.
Fix: Promise not returned
The “Cannot read property ‘then’ of undefined” happens when you forget to use the return keyword return the Promise from the function.
function fetchData(apiUrl) {
// we return the Promise
return fetch(apiUrl).then((response) => {
return response.json();
});
}
// ✅ Runs successfully
fetchData('/api/data')
.then((data) => console.log(data))
Fix: Asynchronous function doesn’t return a value
The “Cannot read property ‘then’ of undefined” error happens in JavaScript when an async function doesn’t return a value, for example, due to an oversight on our part when writing conditional control flow.
JavaScriptCopied!
async function getUserData(userId) {
if (userId) {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
// 😕 No return if userId is absent
}
// ❌ Cannot read property 'then' of undefined if userId is absent
getUserData().then(data => console.log(data));
To fix it, check all flow paths and make sure the async function always returns a value.
JavaScriptCopied!
async function getUserData(userId) {
if (userId) {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
// 👍 Return a resolved Promise even if userId is absent
return Promise.resolve(null);
}
// ✅ Now, we can safely use 'then'
getUserData().then(data => console.log(data));
Fix: Promise is not properly chained
The “Cannot read property ‘then’ of undefined” error occurs in JavaScript when you don’t chain the Promises properly:
JavaScriptCopied!
function fetchAndParseUser(apiUrl) {
fetch(apiUrl)
.then((response) => {
console.log(response);
// 😕 Forgot to return the 'json' Promise
});
}
// ❌ Error: Cannot read property 'then' of undefined
fetchAndParseUser('/api/user')
.then(data => console.log(data))
To fix it in this case, make sure that each then in the chain returns a Promise if we want to continue the chain.
JavaScriptCopied!
function fetchAndParseUser(apiUrl) {
// 👇 Here, we return the 'json' Promise
return fetch(apiUrl)
.then((response) => {
console.log(response);
return response.json(); // 👍 Return the Promise here
});
}
// ✅ Now, we can safely use 'then'
fetchAndParseUser('/api/user')
.then(data => console.log(data))
By Tari Ibaba
/ Last updated on September 21, 2023
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.
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:
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.
By Tari Ibaba
/ Last updated on September 19, 2023
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.
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.
Why make a link open in a new tab in Markdown?
Opening a link in a new tab in Markdown can be beneficial for a number of reasons:
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.
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).
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.
Why don’t many Markdown rendering tools allow links to open in a new tab?
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.
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.
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.
Open link in new tab with HTML <a> tag
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:
MarkdownCopied!
Visit <a href="https://codingbeautydev.com">Coding Beauty</a> for more educational and interesting content.
Open link in new tab with {:target="_blank"}
Alternatively, create a link that opens in a new tab in Markdown with the [link](url){:target="_blank"} syntax. For example:
MarkdownCopied!
Visit [Coding Beauty](https://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.
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.
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:
JavaScriptCopied!
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:
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.tsxCopied!
'use client';
import React, { useEffect } from 'react';
import { useRouter } from 'next/navigation';
export default function Page() {
const router = useRouter();
useEffect(() => {
router.push('https://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.tsxCopied!
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.tsCopied!
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);
}
}
You’ll place middleware.ts file in the same level as your pages directory – which could be the root directory, or src, if enabled.
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.jsCopied!
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.
By Tari Ibaba
/ Last updated on September 30, 2023
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?
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).
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:
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.
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:
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 withclientHeight and clientWidth. Unlike offsetWidth, it includes padding but excludes borders and scrollbars.
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
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
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.
clientWidth and clientHeight are similar to offsetWidth and offsetHeight, but they include padding and exclude borders and scrollbars.
To get the dimensions of the element dynamically, create a windowresize event listener to automatically update the size when the user resizes the browser window.
To get the size of the element before render, replace useEffect with useLayoutEffect.