Uncategorised

Play Updates

Mar 30, 2024

  • Improved compatibility of option input and free-text input.
  • Fix issue where completed puzzle parts were not saving to the browser.

Mar 23, 2024

  • Fixed the issue where Mar 23, 2024 daily puzzle didn’t have the correct option.

10 powerful JavaScript animation libraries for engaging user experiences

Animations. A fantastic way to stand out from the crowd and grab the attention of your visitors.

With creative object motion and fluid page transitions, you not only add a unique aesthetic appeal to your website but also enhance user engagement and create a memorable first impression.

And creating animations can’t get any easier with these 10 powerful JavaScript libraries. Scroll animations, handwriting animations, SPA page transitions, typing animations, color animations, SVG animations… they are endlessly capable. They are the best.

1. Anime.js

An animation creating with Anime.js
An animation created with Anime.js.

With over 43k stars on GitHub, Anime.js is easily one of the most popular animation libraries out there.

It’s a lightweight JavaScript animation library with a simple API that can be used to animate CSS properties, SVG, DOM attributes, and JavaScript objects. With Anime.js, you can play, pause, restart or reverse an animation. The library also provides staggering features for animating multiple elements with follow-through and overlapping actions. There are various animation-related events also included, which we can listen to using callbacks and Promises.

Visit the Anime.js website

2. Lottie

An animation created with Lottie.js
An animation created with Lottie.

Lottie is a library that parses Adobe After Effects animations exported as JSON with the Bodymovin plugin and renders them natively on mobile and web applications. This eliminates the need to manually recreate the advanced animations created in After Effects by expert designers. The Web version alone has over 27k stars on GitHub.

Visit the Lottie website

3. Velocity

An animation created with Velocity.
An animation created with Velocity.

With Velocity you create color animations, transforms, loops, easings, SVG animations, and more. It uses the same API as the $.animate() method from the jQuery library, and it can integrate with jQuery if it is available. The library provides fade, scroll, and slide effects. Besides being able to control the duration and delay of an animation, you can reverse it sometime after it has been completed, or stop it altogether when it is in progress. It has over 17k stars on GitHub and is a good alternative to Anime.js.

Visit the Velocity website

4. Rough Notation

Som Rough Notation annotation styles.
Some Rough Notation annotation styles.

Rough Notation is a JavaScript library for creating and animating colorful annotations on a web page. It uses RoughJS to create a hand-drawn look and feel. You can create several annotation styles, including underline, box, circle, highlight, strike-through, etc., and control the duration and color of each annotation style.

Visit the Rough Notation website

5. Popmotion

An animation created with Popmotion.
An animation created with Popmotion.

Popmotion is a functional library for creating prominent and attention-grabbing animations. What makes it stand out? – there are zero assumptions about the object properties you intend to animate, but instead provides simple, composable functions that can be used in any JavaScript environment.

The library supports keyframes, spring and inertia animations on numbers, colors, and complex strings. It is well-tested, actively maintained, and has over 19k stars on GitHub.

Visit the Popmotion website

6. Vivus

An animation created with Vivus.
An animation created with Vivus.

Vivus is a JavaScript library that allows you to animate SVGs, giving them the appearance of being drawn. It is fast and lightweight with exactly zero dependencies, and provides three different ways to animate SVGs: Delayed, Sync, and OneByOne. You can also use a custom script to draw an SVG in your preferred way.

Vivus also allows you to customize the duration, delay, timing function, and other animation settings. Check out Vivus Instant for live, hands-on examples.

Visit the Vivus website

7. GreenSock Animation Platform (GSAP)

An animation created with GSAP

The GreenSock Animation Platform (GSAP) is a library that lets you create wonderful animations that work across all major browsers. You can use it in React, Vue, WebGL, and the HTML canvas to animate colors, strings, motion paths, and more. It also comes with a ScrollTrigger plugin that lets you create impressive scroll-based animations with little code.

Used in over 11 million sites, with over 15k stars on GitHub, it is a versatile and popular indeed. You can use the GSDevTools from GreenSock to easily debug animations created with GSAP.

Visit the GSAP website

8. Three.js

An animation created with Three.js
An animation created with Three.js

Three.js is a lightweight library for displaying complex 3D objects and animations. It makes use of WebGL, SVG, and CSS3D renderers to create engaging three-dimensional experiences that work across a wide range of browsers and devices. It is a well-known library in the JavaScript community, with over 85k stars on GitHub.

Visit Three.js website

9. ScrollReveal

ScrollReveal animations.
ScrollReveal animations.

The ScrollReveal library lets you easily animate a DOM element as it enters or leaves the browser viewport. It provides various types of elegant effects to reveal or hide an element on-scroll in multiple browsers. And quite easy to use too, with with zero dependencies and over 21k stars on GitHub.

Visit the ScrollReveal website

10. Barba.js

Page transitions created with Barba.js.
Page transitions created with Barba.js.

One creative way to make your website outstanding is to add lively transitions between the pages as your users navigate between them. This produces a better user experience than simply displaying the new webpage or reloading the browser.

And that’s why Barba.js is so useful; this library lets you create enjoyable page transitions by making the site run like a Single Page Application (SPA). It reduces the delay between pages and minimizes the number of HTTP requests that the browser makes. It’s gotten almost 11k stars on GitHub.

Visit Barba.js website

Bonus

11. Mo.js

An animation created with Mo.js
An animation created with Mo.js.

Great library for creating compelling motion graphics.

It provides simple, declarative APIs for effortlessly creating smooth animations and effects that look great on devices of various screen sizes. You can move HTML or SVG DOM elements, or you can create a special Mo.js object, which comes with a set of unique capabilities. It is a reliable and well-tested library, with over 1500 tests written and over 17k stars on GitHub.

Visit the Mo.js website

12. Typed.js

An animation created with Typed.js

The name says it all; an animated typing library.

It types out a specific string character by character as if someone was typing in real-time, allowing you pause the typing speed, and even pause the typing for a specific amount of time. With smart backspacing, it types out successive strings starting with the same set of characters as the current one without backspacing the entire preceding string – as we saw in the demo above.

Also included is support for bulk typing, which types out a group of characters on the screen at the same time, instead of one after the other. Typed.js has over 12k stars on GitHub and is trusted by Slack and Envato.

Visit the Typed.js website

Final thoughts

The world of web animation is vast and dynamic, constantly evolving with the advent of new technologies and libraries. The animation libraries highlighted in this article offer an array of features to create engaging, interactive, and visually appealing experiences for users. They are a testament to the power and flexibility of JavaScript, and demonstrate how animations greatly enhance the user experience.

As a developer, harnessing these tools will no doubt elevate your projects, making them stand out in an increasingly competitive digital landscape.

How to move a line or selection up or down in VS Code

To move a line up or down in Visual Studio Code, use this keyboard shortcut:

  • Windows and Linux: Alt + ↑ (Up arrow) to move line up; Alt + ↓ (Down arrow) to move line down.
  • Mac: Option + ↑ to move line up; Option + ↓ to move line down.
Moving a line up or down in Visual Studio Code.

Move selection up or down in VS Code

Similarly, to move a selection up or down in Visual Studio Code, use this keyboard shortcut:

  • Windows and Linux: Alt + ↑ (Up arrow) to move selection up, Alt + ↓ (Down arrow) to move selection down.
  • Mac: Option + ↑ to move selection up, Option + ↓ to move selection down.
Moving a selection up or down in Visual Studio Code.

Why would you need to move a line/selection up or down in code?

  1. Refactoring: When cleaning up your code, you may need to move lines of code around in and out of functions and classes, to make it more readable and maintainable.
  2. Debugging: Like when fixing that error caused by using a variable before declaration/initializing it; with the keyboard shortcuts you easily move the declaration line up before the usage.
  3. Changing control flow: For those instances where the order of function calls or assignments need to change to reflect a new code logic update.

Commands in Visual Studio Code

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 / Linux: Ctrl + Shit + P
  • Mac: Command + Shift + P

The Move Line Up command in VS Code

To move a line/selection up in Visual Studio Code, we use the Move Line Up command.

Moving a line up with the Move Line Up command.

Or with the keyboard shortcuts:

  • Windows/Linux: Alt + ↑ (Up arrow)
  • Mac: Option + ↑
Moving a line up in Visual Studio Code with the keyboard shortcut.

The Move Line Down command in VS Code

In the same manner, to move a line/selection down in Visual Studio Code, we use the Move Line Down command.

Moving a line down in Visual Studio Code with the Move Line Down command

Or with the keyboard shortcuts:

  • Windows/Linux: Alt + ↓ (Down arrow)
  • Mac: Option +
Moving a line down with keyboard shortcuts

Change keyboard shortcut to move line up or down

Personally, I think they’re fine, but if you don’t like the keyboard shortcut to move the line up or down, then navigate to the Keyboard Shortcuts page and change the keybinding for the Move Line Up and Move Line Down commands.

There are multiple ways 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 Settings popup

To change the keybinding, search for “move line up” or “move line down” in the search bar.

Searching for the Move Line Up command in the Keyboard Shortcuts page
Searching for the Move Line Down command in the Keyboard Shortcuts page of VS Code

Then double-click on the Move Line Up or Move Line Down command, type a new keyboard shortcut, and press the Enter key to carry out the change.

Changing the default keybinding for the Move Line Down command

The change here was Ctrl + E, Ctrl + E – certainly not the smartest choice, but now you’ve seen how it works.

Key takeaways

  • To move a line or selection up or down in Visual Studio Code, use the Alt + ↑ (Up arrow) for up and Alt + ↓ (Down arrow).
  • Moving lines or selections up or down in code can be useful for refactoring, debugging, and changing control flow.
  • You can change the keyboard shortcut to move a line up or down by changing the Move Line Up and Move Line Down command.

How to prevent page refresh on form submit in React

To prevent a page refresh on form submit in React, call event.preventDefault() in the submit event listener.

App.jsx
import React, { useState } from 'react'; function LoginForm() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleEmailChange = (event) => { setEmail(event.target.value); }; const handlePasswordChange = (event) => { setPassword(event.target.value); }; const handleSubmit = (event) => { event.preventDefault(); // Simulate form submission by clearing input fields setEmail(''); setPassword(''); }; return ( <form onSubmit={handleSubmit}> <label> Email <br /> <input type="email" value={email} onChange={handleEmailChange} required /> </label> <br /> <label> Password <br /> <input type="password" value={password} onChange={handlePasswordChange} required /> </label> <br /> <button type="submit" style={{ marginTop: 16 }}> Submit </button> </form> ); } export default function App() { return <LoginForm />; }
The page refresh is prevented in React when the button submits the form.

We use the Event preventDefault() method to stop the default action of the event from happening. In this case, that action was a page refresh, so preventDefault() prevented the page refresh on the form submission.

App.jsx
const handleSubmit = (event) => { event.preventDefault(); // Simulate form submission by clearing input fields setEmail(''); setPassword(''); };

preventDefault() is a property of an Event object, which lets us access and modify event-related data.

We use the onSubmit prop to add a submit event listener to the form; this listener runs when the user clicks the button to submit the form.

All we did here was reset the form, but of course in the real world, you probably want to make an AJAX request to a server with the form data.

App.jsx
const handleSubmit = async (event) => { event.preventDefault(); const user = { email: email, password: password, }; try { const response = await axios.post('http://your-api-url.com', user); console.log(response.data); } catch (error) { console.error(error); } setEmail(''); setPassword(''); };

For the button to submit the form, we must set its type prop to submit

App.jsx
<button type="submit" style={{ marginTop: 16 }}> Submit </button>

With type="submit", the browser also submits the form when the user presses the Enter key in an input field.

Remove type="submit" from the button to prevent page refresh

To prevent page refresh on form submit in React, you can also remove the type="submit" from the button.

When is this useful? You may want to show an alert message or something before submission. In this case, we wouldn’t want type="submit" since it submits the form on button click.

App.jsx
import React, { useState } from 'react'; function LoginForm() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleEmailChange = (event) => { setEmail(event.target.value); }; const handlePasswordChange = (event) => { setPassword(event.target.value); }; const handleSubmit = () => { // Perform custom actions before form submission alert('Are you sure you want to submit the form?'); // Simulate form submission by clearing input fields setEmail(''); setPassword(''); }; return ( <form> <label> Email <br /> <input type="email" value={email} onChange={handleEmailChange} required /> </label> <br /> <label> Password <br /> <input type="password" value={password} onChange={handlePasswordChange} required /> </label> <br /> <button type="button" onClick={handleSubmit} style={{ marginTop: 16 }}> Submit </button> </form> ); } export default function App() { return <LoginForm />; }
Prevent a page refresh on form submit in React to show an alert dialog before submission.

We used type="button" on the button, but that’s as good as not having a type attribute. It doesn’t do anything on click.

Key takeaways

  • To prevent page refresh on form submit in React, call event.preventDefault() in the submit event listener.
  • Set type="submit" to ensure the form submits on button click or Enter press. Remove it when you don’t want this.
  • Remove type="submit" when you need to do something after the button click before submitting the form, e.g., show a dialog, make an initial request, etc.

How to Fix the “Unexpected reserved word ‘enum'” Error in JavaScript

The “Unexpected reserved word ‘enum'” syntax error happens in JavaScript happens because enum is not a valid keyword in JavaScript, but it is reserved.

The "Unexpected reserved word 'enum'" syntax error happening in JavaScript.

It was reserved in the ECMAScript specification in case it may become valid in the future.

If it wasn’t reserved, devs could start using it as variable names in their code – making future keyword use impossible!

JavaScript
// ❌ SyntaxError: Unexpected reserved word 'enum' enum Color { Red, Blue, Green } const color = Color.Red;

To fix it, represent the enumeration in another way, or change the file to TypeScript.

Fix: Create a JavaScript enum the right way

Enums are useful stuff, but since there’s no enum keyword in JS, we’ll have to find others way to create and use them.

One powerful way to create an enumeration is with an object with JavaScript symbol properties:

JavaScript
const daysOfWeek = { Mon: Symbol('Mon'), Tue: Symbol('Tue'), Wed: Symbol('Wed'), Thu: Symbol('Thu'), Fri: Symbol('Fri'), Sat: Symbol('Sat'), Sun: Symbol('Sun'), }; const dayOfWeek = daysOfWeek.Tue;

With JavaScript symbols, we make sure that the constants are always different values, as every symbol is unique.

No need to worry duplicates – pretty convenient, right?

If we used this:

JavaScript
const daysOfWeek = { Mon: 'Mon', Tue: 'Tue', Wed: 'Wed', Thu: 'Thu', Fri: 'Fri', Sat: 'Sat', Sun: 'Sun', }; const dayOfWeek = daysOfWeek.Tue;

Someone could easily reassign the object’s properties to something else, giving us something more to worry about.

Fix: Just use TypeScript

Ah, TypeScript.

Alway there for us. Filled to the top with juicy modern stuff.

I mean enums aren’t so modern, but it’s one thing TS has that JS doesn’t.

Our first JS code runs flawlessly in TypeScript.

TypeScript
// ✅ No error - enums all the way! enum Color { Red, Blue, Green } const color = Color.Red;

So, if you really need that enum keyword – even though much of the TypeScript community seems to frown on it – change that file extension.

Oh, it could even be that it’s TypeScript you wanted all along. As it happened here.

Here, this person was new to TypeScript on Node (we’ll all been there) and ran his TS file with the node command directly.

Well, Node didn’t care about the extension and just treated the entire thing like a JavaScript file.

The easy solution was to compile it first with tsc before running node on the JS output. Or to use ts-node on the TypeScript file directly.

Key takeaways

So, the few things to keep in mind on fixing the “Unexpected reserved keyword ‘enum'” error in JavaScript:

  1. enum is a no-go in JavaScript (for now): JavaScript doesn’t have enum. It’s reserved for future use.
  2. Use objects with symbol properties: Want to create enumerations in JavaScript? Use objects with symbol properties.
  3. Symbols keep your code safe: Symbols are unique. They stop others from messing with your object’s properties.
  4. TypeScript has enum: Need enum? Switch to TypeScript. It’s got your back.
  5. Remember to compile TypeScript: Using TypeScript for Node.js? Compile your TypeScript files first. Or quickly use ts-node.

How to Fix the “structuredClone is not defined” Error in Node.js

The “structuredClone is not defined” error occurs when you try to use the structuredClone()/ method in JavaScript, but it’s not defined.

The "structuredClone is not defined" error occuring in a terminal.
The “structuredClone is not defined” error occuring in a terminal.

To fix it, install Node.js 17 or a newer version. Once you’ve updated Node.js, you can use structuredClone() to clone objects with all their properties and methods.

What causes the “structuredClone is not defined” error?

If you try to use the structuredClone() method in a script that’s running with a Node.js version lower than 17, you will encounter this error.

The structuredClone() method is used to create a deep copy of an object. It’s a built-in function in JavaScript and is used to clone an object with all its properties and methods.

But when the structuredClone() method is not defined, it means that the server environment doesn’t recognize the function and cannot perform the action.

Fix: update Node.js

To fix the “structuredClone is not defined” error in JavaScript, you need to install Node.js 17 or a newer version. If you’re using an older version of Node.js, it will throw an error when you try to use structuredClone().

Install from website

To download Node.js, visit the official website and opt for the LTS version, as it offers superior stability. As of the time of writing this article, the most recent LTS release of Node.js is v18.15.0.

The Node.js download page on the official website.
The Node.js download page on the official website.

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

After installing, you can use the structuredClone method to clone an object:

JavaScript
const obj = { name: 'Mike', friends: [{ name: 'Sam' }] }; const clonedObj = structuredClone(obj); console.log(obj.name === clonedObj); // false console.log(obj.friends === clonedObj.friends); // false

Key takeaways

If you get the “structuredClone is not defined” error when using the structuredClone() method in JavaScript, it means that the method is unavailable. To fix the problem, update your Node.js to a version newer than 17. You can get the latest version from the official Node.js website or install the nodejs package using Chocholatey.

How to Fix the “Unexpected reserved word (await)” Error in JavaScript

The “unexpected reserved word (await)” error occurs in JavaScript when you use the await keyword in a function that is not specified as async. To fix it, add an async modifier to the function to mark it as async.

The "Unexpected reserved word 'await'" error occurring in JavaScript.
The “Unexpected reserved word ‘await'” error occurring in JavaScript.

Here’s an example of the error occurring:

index.js
function getName() { // ❌ SyntaxError: Unexpected reserved word const str = await Promise.resolve('Coding Beauty'); return str; }

Note: As this is a syntax error, the function doesn’t need to be invoked for it to be detected, and no part of the code runs until it is resolved.

The async and await keywords work together in JavaScript (hence the commonly used term, async/await); to use the await keyword in a function, you must add the async modifier to the function to specify that it is an async function.

JavaScript
// ✅ Use "async" keyword modifier async function getName() { // ✅ Successful assignment - no error const str = await Promise.resolve('Coding Beauty'); return str; }

Fix “Unexpected reserved word (await)” error in nested function

If you’re using the await keyword, it’s likely that you already know that it has to be in an async function. What probably happened is that you nested functions and mistakenly ommited the async modifier from the innermost function containing the await keyword.

For example:

JavaScript
// ❌ SyntaxError: Unexpected reserved word export const createTask = async ({ description }) => // ❌ "async" keyword missing from innermost function (dispatch) => { await fetch('https://example.com/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ description }), }); dispatch({ type: 'taskCreated', description }); };

For await to work, the deepest function in the nesting hierarchy is required to be specified as async. It won’t work even if any or all of the outer functions are marked as async.

So we resolve the error in this case by adding the async modifier to the innermost function:

JavaScript
// ✅ No error export const createTask = async ({ description }) => // ✅ Innermost function marked as async async (dispatch) => { await fetch('https://example.com/tasks', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ description }), }); dispatch({ type: 'taskCreated', description }); };

In this example, we should be able to remove the async keyword from the outer function, as it isn’t performing any asynchronous operations with await, but this depends on whether the caller of createTask() is expecting it to return a Promise or not.

Here’s another example where this mistake frequently happens; using await in an array looping method:

JavaScript
// ❌ SyntaxError: Unexpected reserved word async function processPhotos(photoIds) { const data = await Promise.all(photoIds.map((photoId) => { const res = await fetch(`http://example.com/photos/${photoId}`); return await res.json(); })); // process data... }

Like in the previous example, the error occurs because the async keyword modifier is absent from the map() callback, even though it’s present in the function that calls map(). The fix is the same, add async to the map() callback.

JavaScript
// ✅ No error async function processPhotos(photoIds) { const data = await Promise.all( photoIds.map(async (photoId) => { const res = await fetch(`http://example.com/photos/${photoId}`); return await res.json(); }) ); // processing... }

Use await at top level

If you’re trying to use await at the top level of your file, you’ll need to set the type attribute to "module" in the script tag referencing the file in the HTML. This works when your code runs in browser environments.

For example:

index.html
<script type="module" src="index.js"></script>

Now you’ll be able to use await at the global scope in your file, e.g.:

index.js
console.log(await Promise.resolve('Coding Beauty'));

If you’re using Node.js, you’ll need to set the type attribute to "module" in your package.json file.

package.json
{ "name": "cb-js", "type": "module", "version": "1.0.0", "main": "index.js", "license": "MIT", // other fields... }

If there’s no package.json in your project directory, you can create one with the following command

Shell
# NPM npm init -y # Yarn yarn init -y

The await keyword will now work at the top level of your project files.

How to Convert Hours and Minutes to Seconds in JavaScript

To convert hours and minutes to seconds in JavaScript:

  1. Multiply the hours by 3600 to convert it to seconds.
  2. Multiply the minutes by 60 to convert it to seconds.
  3. Add these seconds to the seconds time value to get the total seconds.

For example:

JavaScript
function toSeconds(hours, minutes, seconds) { return hours * 3600 + minutes * 60 + seconds; } console.log(toSeconds(2, 15, 10)); // 8110 console.log(toSeconds(1, 5, 30)); // 3930

We create a reusable toSeconds() function to easily convert the hours and minutes to seconds.

The function is quite easy to understand; 1 hour equals 3600 seconds, so we multiply the hour value by 3600 to get the seconds equivalent. Similarly, 1 minute equals 60 seconds, so we multiply the minute value by 60 to get the seconds equivalent.

After this, we add the equivalent seconds values to the seconds argument to get the total seconds.

We could rewrite the function to accept the time values as named properties of an object, instead of as multiple parameters.

JavaScript
function toSeconds({ h: hours, m: minutes, s: seconds }) { return hours * 3600 + minutes * 60 + seconds; } console.log(toSeconds({ h: 2, m: 15, s: 10 })); // 8110 console.log(toSeconds({ h: 1, m: 5, s: 30 })); // 3930

This approach makes it easier to understand the role of each value passed to the function, a

Convert HH:mm:ss to seconds in JavaScript

Sometimes the time input to convert to seconds is a string in a time format, like HH:mm:ss. To convert to seconds in this case, we’ll separate the individual time values by the separator (: in this case), cast them each to numbers, and perform the same time conversion steps done in our previous examples.

For example:

JavaScript
function toSeconds(timeStr) { const [hours, minutes, seconds] = timeStr.split(':').map(Number); return hours * 3600 + minutes * 60 + seconds; } console.log(toSeconds('02:15:10')); // 8110 console.log(toSeconds('01:05:30')); // 3930

The input string here is in the HH:mm:ss format; the hour, minute, and second values are separated by a colon (:) and are each represented by a minimum of 2 digits.

The String split() method splits a string into an array of substrings separated by a given separator in the original string. We pass a colon as the separator to get an array of the individual time values.

JavaScript
const timeStr = '02:15:10'; console.log(timeStr.split(':')); // [ '02', '15', '10' ]

After getting this array, we use the map() method to transform each time value into a number. The map() method takes a callback and calls it on each element of an array and uses the result to populate a new array. For our scenario, the callback is simply the Number() constructor, so each time value in the array is converted to a number.

JavaScript
console.log(['02', '15', '10'].map(Number)); // [ 2, 15, 10 ]

Note

This:

JavaScript
const [hours, minutes, seconds] = timeStr.split(':').map(Number);

is equivalent to this:

JavaScript
const [hours, minutes, seconds] = timeStr .split(':') .map((str) => Number(str));

The second one is longer, but it makes it clear exactly what arguments are passed to the map() callback. In the first one, map() automatically passes 3 arguments to its callback, which could be problematic if the callback returns a different result depending on the number of arguments it receives, for instance, a parseInt() callback.

We then use a destructuring assignment to unpack the number array values into separate hour, minute, and second variables.

JavaScript
const [hour, minute, seconds] = [2, 15, 10]; console.log(hour); // 2 console.log(minute); // 15 console.log(seconds); // 10

After doing this, we perform the same multiplication and addition we did in the first example, to convert the hours and minutes to seconds and get the total seconds.

How to Get the Window’s Width and Height in React

To get the width and height of the window in React, use window.innerWidth and window.innerHeight.

App.js
import { useRef } from 'react'; export default function App() { const windowSize = useRef([window.innerWidth, window.innerHeight]); return ( <div> <h2>Width: {windowSize.current[0]}</h2> <h2>Height: {windowSize.current[1]}</h2> </div> ); } 
Getting the window width and height in React.

The innerWidth property returns the interior width of the window in pixels, including the width of the vertical scrollbar, if it’s present.

Similarly, innerHeight property returns the interior height of the window in pixels, including the height of the horizontal scrollbar, if it is present.

Since we are getting the window width and height only once – when the component mounts – we use the useRef() hook to store them.

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.

Get window width and height on resize in React

To get the window width and height on resize in React:

  1. Get the window width and height with window.innerWidth and window.innerHeight.
  2. Add an event listener for the resize event on the window object.
  3. Update the window width and height in this event listener.

In the previous example, we needed to get the window width and height only once, and we used a ref to store it.

If you instead want to get the window’s width and height when it is resized, you’ll need to add a resize event listener to the window object and create a state variable to track changes to the width and height.

App.js
import { useState, useEffect } from 'react'; export default function App() { const [windowSize, setWindowSize] = useState([ window.innerWidth, window.innerHeight, ]); useEffect(() => { const handleWindowResize = () => { setWindowSize([window.innerWidth, window.innerHeight]); }; window.addEventListener('resize', handleWindowResize); return () => { window.removeEventListener('resize', handleWindowResize); }; }, []); return ( <div> <h2>Width: {windowSize[0]}</h2> <h2>Height: {windowSize[1]}</h2> </div> ); }
The window’s width and height get updated when it’s resized.

We use the useState React hook to create a state variable that will be updated whenever the height or width of the window changes.

The useState hook returns an array of two values. This first is a variable that stores the state, and the second is a function that updates the state when it is called.

JavaScript
const [windowSize, setWindowSize] = useState([ window.innerWidth, window.innerHeight, ]);

The useEffect hook is used to perform an action when a component first renders, and when one or more specified dependencies change. In our example, the action is to add the event listener for the resize hook with the addEventListener() method.

We pass an empty dependencies array to the useEffect, so that it gets called only once in the component’s lifetime, and the resize event listener is only registered once – when the component first renders.

App.js
useEffect(() => { const handleWindowResize = () => { setWindowSize([window.innerWidth, window.innerHeight]); }; window.addEventListener('resize', handleWindowResize); return () => { window.removeEventListener('resize', handleWindowResize); }; }, []);

In the resize event listener, we update the state variable with the new height and width of the window.

The function we return in useEffect is a function that performs clean-up operations in the component. We use the removeEventListener() method to remove the resize event listener in this clean-up function and prevent a memory leak.

Note

useEffect‘s cleanup function runs after every re-render where its dependencies change in addition to when the component unmounts. This prevents memory leaks that happen when an observable prop changes value without the observers in the component unsubscribing from the previous observable value.

Since we pass an empty dependencies array, its dependencies won’t ever change, so in this case, it’ll run only when the component unmounts.

How to Easily Handle the onScroll Event in React

To handle the onScroll event on a React element, assign a function to the onScroll prop of the element and use the event object to perform an action. That action will occur whenever the user scrolls up or down on the page.

For example:

App.jsx

import { useState } from 'react';

export default function App() {
  const [scrollTop, setScrollTop] = useState(0);

  const handleScroll = (event) => {
    setScrollTop(event.currentTarget.scrollTop);
  };

  return (
    <div>
      Scroll top: <b>{scrollTop}</b>
      <br />
      <br />
      <div
        style={{
          border: '1px solid black',
          width: '400px',
          height: '200px',
          overflow: 'auto',
        }}
        onScroll={handleScroll}
      >
        {[...Array(10)].map((_, i) => (
          <p key={i}>Content</p>
        ))}
      </div>
    </div>
  );
}
The text is updated when the component's onScroll event fires.
The text is updated when the component’s onScroll event fires.

The function (event listener) passed to the onScroll prop is invoked whenever the viewport is scrolled. It is called with an event object, which you can use to perform actions and access information related to the scroll event.

The currentTarget property of this event object returns the element that the onScroll listener was attached to.

Tip: If you’re not sure of when to use the event object’s currentTarget or target properties, this article might help: Event target vs currentTarget in JavaScript: The Important Difference.

We use the element’s scrollTop property to get how far the element’s scrollbar is from its topmost position. Then we update the state variable with the new value, and this reflects on the page.

Note: We used the useState hook to manage the state. This hook returns an array of two values, where the first is a variable that stores the state, and the second is a function that updates the state when it is called.

Handle onScroll event on window object in React

We can also handle the onScroll event on the global window object, to perform an action when the viewport is scrolled. We can do this with the addEventListener() method:

App.js

import { useState, useEffect } from 'react';

export default function App() {
  const [scrollTop, setScrollTop] = useState(0);

  useEffect(() => {
    const handleScroll = (event) => {
      setScrollTop(window.scrollY);
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    <div>
      <div
        style={{
          position: 'fixed',
          padding: '10px 0',
          top: '0',
          backgroundColor: 'white',
          borderBottom: '1px solid #c0c0c0',
          width: '100%',
        }}
      >
        Scroll top: <b>{scrollTop}</b>
      </div>
      <div style={{ marginTop: '50px' }}>
        {[...Array(30)].map((_, i) => (
          <p key={i}>Content</p>
        ))}
      </div>
    </div>
  );
}
The text is updated when the window's onScroll event fires.
The text is updated when the window’s onScroll event fires.

The addEventListener() method takes up to two arguments:

  1. type: a string representing the event type to listen for.
  2. listener: the function called when the event fires.

It also takes some optional arguments, which you can learn more about here.

We call addEventListener() in the useEffect hook to register the listener once the component renders as the page loads. We pass an empty dependencies array to useEffect so this registration happens only once. In the cleanup function, we call the removeEventListener() method to unregister the event listener and prevent a memory leak.

In the onScroll listener, we access the Window scrollY property to display the number of pixels that the page has currently scrolled horizontally.