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.
The get the width of the browser window on resize in React, add a resize event listener to the window object, then access the innerWidth property in the listener.
The text is updated with the width of the window when it is resized.
The innerWidth property returns the interior width of the window in pixels, including the width of the vertical scrollbar, if it is present.
The resize event is fired whenever the width or height of the window/document view changes.
We use the useState React hook to create a state variable that will update whenever the width of the window changes.
The useState hook returns an array of two values. The first is a variable that stores the state, and the second is a function that updates the state when it is called.
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 useEffect, so that it is called only once in the component’s lifetime, and the resize event listener is only registered once – when the component first renders.
In the resize event listener, we update the state variable with the new window width.
Note: useEffect‘s cleanup function runs after every re-render, not only 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.
Get window height on resize
We can do a similar thing to get the window’s height on resize, but we’ll use the window object’s innerHeight property instead in the resize event listener:
Autosave has grown in popularity recently and become the default for many developers and teams, a must-have feature for various code editors. Apps like Visual Studio stubbornly refuse to fully provide the feature, and others make it optional. WebStorm, PHPStorm, and other JetBrains products have it enabled by default; for VSCode, you have to turn it on if you want it.
So obviously, we have two opposing views on the value of autosave because even though it can be highly beneficial, it has its downsides. In this article, we’ll look at both sides of the autosave divide, good causes for turning it off and good causes not to.
Why you should stop autosaving your code
First, some reasons to think twice before enabling autosave in your code editor:
1. Higher and wasted resource usage
When using tools that perform an expensive action any time the file is changed and saved, like build watchers, continuous testing tools, FTP client file syncers, etc, turning on autosave will make these actions much more often. They will also happen when there are errors in the file, and when you make a tiny change. It might instead be preferable for these tools to run only when they need to; when you reach a point where you really want to see the results of your changes.
With greater CPU and memory usage comes lower battery usage and more heat from higher CPU temperature. Admittedly, this will continue to become less and less of an issue as computers increase in processing power, memory capacity, and battery life across the board. But depending on your particular situation, you might want to conserve these things as much as possible.
2. Harder to recover from unexpected errors
With autosave enabled, any single change you make to your code file is written to disk, whether these changes leave your file in a valid state or not. This makes it harder to recover from unwanted changes.
What if you make an unintended and possibly buggy change, maybe from temporarily trying something out, and then close the file accidentally or unknowingly (autosave makes this more likely to happen)? With your Undo history wiped out, it will be harder to recover the previous working version of the file. You might even forget how the code used to look before the change, and then have to expend some mental effort to take the code back to what it was.
Of course, using version control tools like Git and Mercurial significantly decrease the chances of this happening. Still, the previous working version of the file you would want to recover could be one with uncommitted changes, not available from version control, especially if you don’t commit very frequently or you have a commit scheduling determined by more than just the code working after small changes, e.g., committing when a mini milestone is reached, committing after every successful build, etc.
So if you want to continue enjoying the benefits of auto-save while minimizing the possibility of this issue occurring, it’s best if you always use source control and have a frequent commit schedule.
3. No auto-formatting on save
Many IDEs and text editors have a feature that automatically formats your code, so you can focus on the task at hand. For example, VSCode has built-in auto-formatting functionality, and also allows extensions to be written to provide more advanced or opinionated auto-formatters for various languages and file extensions.
These editors typically provide an option to format the file when it is saved. For manual saving, this makes sense, as usually you Ctrl/Cmd + S after making a small working change to a file and stop typing. This seems like a great point for formatting, so it’s a great idea to combine it with the saving action so there’s no need to think about it.
However, this feature isn’t very compatible with auto-save, and that’s why editors/IDEs like WebStorm and VSCode do not format your code for you on auto-save (you can still press Ctrl (Cmd) + S for it to happen, but isn’t one of the reasons for enabling auto-save to avoid this over-used keyboard shortcut?).
For one, it would probably be annoying for the cursor to change position due to auto-formatting as you’re typing. And then, there’s also the thing we already talked about earlier – the file won’t always be syntactically valid after an auto-save, and the auto-formatter will fail.
There is one way though, to have auto-formatting while still leaving auto save turned on, and that is enabling auto-formatting on commit. You can do this using Git pre-commit hooks provided by tools like Prettier and Husky.
Still only happens on commit though, so unless your code is not too messed up or you’re ready to format manually, you’ll have to endure the disorderliness until your next commit (or just press that Ctrl + S).
4. Can be distracting
If you have a tool in your project that performs an action when files are saved and indicate this visually in your editor, i.e, a pop-up notification to indicate recompilation, output in the terminal to indicate rebuilding, etc. With auto-save turned on, it can be a bit distracting for these actions to occur whenever you stop typing for a little while.
For instance, in this demo, notice how the terminal output in VSCode changes wildly from typing in a small bunch of characters:
Text editors have tried to fix this problem (and the resource usage problem too) by adding autosave delays; waiting a certain period of time since the file was last changed before actually committing the changes to disk.
This reduces the frequency at which the save-triggering actions occur and solves the issue to an extent, but it’s a trade-off as lack of immediate saving produces another non-ideal situation.
5. Auto-save is not immediate
Having an auto-save delay means that your code file will not be saved immediately. This can lead to some problems:
Data loss
Probably the biggest motivator for enabling auto-save is to reduce the likelihood that you’ll lose all the hard work you’ve put into creating code should an unexpected event like a system crash or the forced closing of the application occur. The higher your auto-save delay, the greater the chance of this data loss happening.
VSCode takes this into account; when its auto-save delay is set to 2 or more seconds, it will show the unsaved file indicator for a recently modified file, and the unsaved changes warning dialog if you try to close the file until the delay completes.
On-save action lags
Tools that run on save like build watchers will be held back by the auto-save delay. With manual save, you know that hitting Ctrl + S will make the watcher re-build immediately, but with delayed auto-save, you’ll have to experience the lag between your finishing and the watcher reacting to changes. This could impact the responsiveness of your workflow.
Why you should autosave your code
The reasons above probably won’t be enough to convince many devs to disable autosave. It is a fantastic feature after all. And now let’s look at some of the reasons why it’s so great to have:
If you use manual save, you probably press this keyboard shortcut hundreds or even thousands of times in a working day. Auto-saving helps you avoid this entirely. Even if you’re very used to it now, once you get used to your files being autosaved, you’ll be hesitant to back to the days of carrying out the ever-present chore of Ctrl + S.
Eradicating the need for Ctrl + S might even lower your chances of suffering from repetitive strain injury, as you no longer have to move your wrists and fingers over and over to type the key combination.
The time you spend pressing the key combination to save a file might not seem like much, but it does add up over time. Turning auto-save on lets you use this time for more productive activities. Of course, if you just switched to auto-save, you’ll have to work on unlearning your Ctrl + S reflex for this to be a benefit to you.
3. Certainty of working with latest changes
Any good automation turns a chore into a background operation you no longer have to think about. This is what auto-save does to saving files; no longer are you unsure of whether you’re working with the most recent version of the file. Build watchers and other on-file-change tools automatically run after the file’s contents are modified, and display output associated with the latest file version.
4. Avoids errors due to file not being saved
This follows from the previous point. Debugging can be a tedious process and it’s not uncommon for developers to forget to save a file when tirelessly hunting for bugs. You probably don’t want to experience the frustration of scrutinizing your code, line after line, wondering how this particular bug can still exist after everything you’ve done.
You might think I’m exaggerating, but it might take up to 15 (20? 30??) minutes before you finally notice the unsaved file indicator. Especially if you’ve been trapped in a cycle of making small changes, saving, seeing the futility of your changes, making more small changes, saving… when you’re finally successful and pressing Ctrl + S is the only issue, you might just assume your change didn’t work, instead of checking for other possible reasons for the reoccurrence of the error.
5. Encourages smaller changes due to triggering errors faster
When a tool performs an action due to a file being saved, the new contents of the file might be invalid and trigger an error. For example, a test case might fail when a continuous testing tool re-runs or there might be a syntax error when a build watcher re-builds.
Since this type of on-file-change action occur more (possibly much more) when files are auto-saved when you type code that causes an error, it will take a shorter time for the action to happen and for you to be notified of the error. You would have made a smaller amount of code changes, which will make it easier to identify the source of the error.
Conclusion
Autosave is an amazing feature with the potential to significantly improve your quality of life as a developer when used properly. Still, it’s not without its disadvantages, and as we saw in this article, enabling or disabling it is a trade-off to live with. Choose auto-format on save and lower CPU usage, or choose to banish Ctrl + S forever and gain the certainty of working with up-to-date files.
What are your views concerning the autosave debate? Please let me know in the comments!
To get the last part of a URL in JavaScript, use .split('/') to split the URL string into an array of each part, then use .at(-1) to get the last part from the array.
The Arraysplit() method takes a character and splits a string into an array of substrings that were separated by that character in the string. A URL’s segments are separated by the / character, so we pass this character to split() to create an array with each URL segment as an element.
After getting this array, we use the Arrayat() method to get a single element from it. at() is a new ES2022 addition that accepts both positive and negative integers.
Passing negative integers to at() makes it count from the end of the array, so -1 gives the first element from the end (last element) – the last part of the URL.
You might be getting the last part of the URL to remove it from the URL string. If that’s what you want, there’s no need to get the last part of the URL at all – we can remove it easily with the slice() and lastIndexOf() methods.
We use the StringlastIndexOf() method to get the position of the last occurrence of the / character, because this is the point just before the last part of the URL starts in the string.
Stringslice() returns the portion of a string between specified start and end indexes, passed as the first and second arguments respectively. We pass 0 as the first argument so the resulting substring starts from the first character, and we pass the result of lastIndexOf() as the second argument so that the substring ends at the index before the last part of the URL starts in the string.
The “cannot find name ‘console'” error occurs when you try to access the global console object in a TypeScript file. To fix it, install the @types/node NPM package for Node.js environments, or add 'DOM' to the lib array in your tsconfig.json for browser environments.
The “cannot find name ‘console'” TypeScript error occuring in VSCode.
index.tsCopied!
/*
* Cannot find name 'console'. Do you need to change your
* target library? Try changing the 'lib' compiler option
* to include 'dom'.ts(2584)
*/
console.log('coding beauty');
Install Node.js typings
If your code is running in a Node.js environment, you can fix the “cannot find name ‘console'” error by running the following command at the root of your project directory.
ShellCopied!
npm i -D @types/node
# Yarn
yarn add --dev @types/node
This should resolve the error for Node.js runtimes.
Add typings to types array in tsconfig.json
In some cases, this is all you need to fix the error. But if it persists, you might need to add the newly installed typings to the types array of your tsconfig.json file.
Including 'node' string in the tsconfig.jsontypes array will make the Node.js typings visible to the TypeScript compiler.
tsconfig.jsonCopied!
{
"compilerOptions": {
"types": [
// other types...
"jest"
]
// other settings...
}
}
Add 'DOM' to lib array in tsconfig.json file
If your code is running in a browser, trying adding a 'DOM' string to the lib array in your tsconfig.json file.
tsconfig.jsonCopied!
{
"compilerOptions": {
"lib": [
// other libs...
"ES6",
"DOM"
],
// other settings...
},
}
Doing this tells TypeScript that your code is client-side code, and it should provide a set of type definitions for built-in JavaScript APIs found in browser environments.
Restart code editor
If the error persists after trying out all these solutions, restarting your IDE or code editor might help.
Conclusion
To fix the “cannot find name ‘console’ error” in TypeScript, install Node typings if your code runs in Node.js, or add the 'DOM' string to your types array in your tsconfig.json if running in a browser.
To get the number of months between two dates in JavaScript:
Use date1.getMonth() - date2.getMonth() to get the month difference between the two dates.
Use date1.getYear() - date2.getYear() to get the difference between the two dates.
Add the month difference to the year difference multiplied by 12, i.e, monthDiff + yearDiff * 12.
For example:
JavaScriptCopied!
function differenceInMonths(date1, date2) {
const monthDiff = date1.getMonth() - date2.getMonth();
const yearDiff = date1.getYear() - date2.getYear();
return monthDiff + yearDiff * 12;
}
// June 5, 2022
const date1 = new Date('2022-06-05');
// March 17, 2021
const date2 = new Date('2021-03-17');
const difference = differenceInMonths(date1, date2);
console.log(difference); // 15
Our reusable differenceInMonths() function takes two Date objects and returns the difference in months between them. The first argument is the start date, and the second is the end date.
The DategetMonth() method returns a zero-based number that represents the month of a particular date.
Note: “Zero-based” here means that 0 is January, 1 is February, 2 is March, etc.
Apart from subtracting the months, we also need to subtract the years, because the two dates might have different years, and this would of course affect the number of months between them. We use the getFullYear() method to get the years of the dates and subtract them.
The DategetFullYear() method returns a number that represents the year of a particular date.
A year equals 12 months, so after getting the year difference, we multiple it by 12 to get the equivalent months, and add it to the month difference.
2. date-fnsdifferenceInMonths() function
Alternative we can use the differenceInMonths() function from the date-fns NPM package to quickly get the difference in months between two dates in JavaScript. It works just like our own differenceInMonths() function, taking two Date objects and returning the difference in their months.
JavaScriptCopied!
import { differenceInMonths } from 'date-fns';
const date1 = new Date('2022-08-10');
const date2 = new Date('2020-02-24');
const difference = differenceInMonths(date1, date2);
console.log(difference); // 29
To capitalize the first letter of each word in a string in React:
Split the string into an array of words with .split('').
Iterate over the words array with .map().
For each word, return a new word that is an uppercase form of the word’s first letter added to the rest of the word, i.e., word.charAt(0).toUpperCase() + word.slice(1).
Join the words array into a string with .join(' ').
After creating the array of words, we call the map() method on it, with a callback function as an argument. This function is called by map() and returns a result for each word in the array.
In the function, we get the word’s first character with charAt(), convert it to uppercase with toUpperCase(), and concatenate it with the rest of the string.
We use the Stringslice() method to get the remaining part of the string. Passing 1 to slice() makes it return the portion of the string from the second character to the end.
Note: String (and array) indexing is zero-based JavaScript, so the first character in a string is at index 0, the second at 1, and the last at str.length-1
Lastly, we concatenate the words into a single string, with the Arrayjoin() method
Passing a space (' ') to join() separates the words by a space in the resulting string.
JavaScriptCopied!
// Welcome To Coding Beauty
console.log(['Welcome', 'To', 'Coding', 'Beauty'].join(' '));
After creating the capitalizeWords() function, we call it as the component is rendered by wrapping it in curly braces ({ }) in our JSX code.
In this article, we’re going to learn how to easily convert a decimal number to its hexadecimal equivalent in JavaScript. And we’ll look at some real-world scenarios where we’ll need to do this.
NumbertoString() method
To convert a decimal to hex in JavaScript, call the toString() method on the decimal, passing 16 as the radix argument, i.e., num.toString(16). The toString() method will return the string representation of the number in hexadecimal form.
For example:
JavaScriptCopied!
const num = 60;
const hex = num.toString(16);
console.log(hex); // 3c
// Use parentheses when calling toString() directly
const hex2 = (60).toString(16);
console.log(hex2); // 3c
The NumbertoString() method returns the string representation of a number. If a base is specified with the first argument, the number is represented in that base. We pass 16 to use base 16, which is the hexadecimal base.
The hexadecimal base uses 16 symbols to represent numbers:
0 to 9 to represent values 0 to 9
a to f (A to F) to represent values 10 to 16. The letters are case-insensitive, so 3C2b is exactly the same value as 3c2B.
Call toString() on number literal
If you call toString() on a number literal directly, ensure you wrap it in parentheses (( )) or use two dots (..before toString():
If you use only one dot without parentheses, the JavaScript parser treats it as part of the number literal – a decimal point – instead of a member access operator.
JavaScriptCopied!
console.log(40.); // 40
console.log(20.); // 20
So there will be an error, since there will be no member access operator before the member name.
We create a reusable rgbToHex() function to convert the RGB code to its hex equivalent.
We use the padToTwo() function to pad a hex code to two digits, e.g, f -> 0f.
After converting the R, G, and B decimal values to their hexadecimal representations, we join them together in a string prefixed with the # character to form the hex color code.
We could modify the function to also accept RGBA values, where the A is a percentage value (between 0 and 1) used to specify color opacity. A will be the first two characters of the hex color code, having a value between 00 (0 or 0%) and ff (255 or 100%)
JavaScriptCopied!
function decToHex(dec) {
return dec.toString(16);
}
function padToTwo(str) {
return str.padStart(2, '0');
}
function rgbToHex(r, g, b, a) {
const hexR = padToTwo(decToHex(r));
const hexG = padToTwo(decToHex(g));
const hexB = padToTwo(decToHex(b));
// Set "a" to 1 if not specified
const aAbsolute = Math.round((a ?? 1) * 255);
const hexA = padToTwo(decToHex(aAbsolute));
return `#${hexA}${hexR}${hexG}${hexB}`;
}
console.log(rgbToHex(255, 128, 237)); // #ffff80ed
console.log(rgbToHex(195, 151, 151, 0.5)); // #80c39797
console.log(rgbToHex(16, 16, 16, 0.69)); // #b0101010
We use the :hover pseudo-class to style an element when the user hovers over it with the mouse pointer.
Change element style on hover with inline styling
We can also change an element’s style on hover using inline styles and the element’s style prop. To do this, we need to create state that will determine whether the hover styles should be applied to the element or not. We also need to add event listeners for the mouseenter and mouseleave and change the state’s value in them.
We use the useState hook to create the boolean state variable that will determine whether the hover styles should be applied to the element or not. useState returns an array of two values. The first is a variable that stores the state, and the second is a function that updates the state when it is called.
We use the onMouseEnter prop to listen for the mouseenter event to detect when the mouse enters within the element’s bounds.
Note: While we could also listen for the mouseover event to detect hover, this event is triggered on 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.
Similarly, we use the onMouseLeave prop to listen for the mouseleave to detect when the mouse leaves the element’s bounds.
We use the ternary operator to conditionally set the style based on the boolean state.
Change element style on hover with custom component
If you frequently use the inline styles approach to change the element’s style on hover, it will be better if you encapsulate the logic into a custom component, so you can reuse it in multiple places in your codebase and avoid unnecessary duplication.
The Hover component takes a callback function as its child. It passes the state variable storing the hover state to this callback so that you can use it to change the style of the element returned from the callback. Hover calls the callback to render this element.
It wraps the element with a div, on which it listens for the mouseenter and mouseleave events to update the state variable. We set the display CSS property to contents on the wrapper because it plays no visual role on the page. It’s only there for the hover detection.
The “cannot access before initialization” reference error occurs in JavaScript when you try to access a variable before it is declared with let or const and initialized in the same scope. To fix it, initialize the variables before accessing them.
The “cannot access before initialization” reference error occurring in JavaScript.
Here are some examples of the error occurring:
index.jsCopied!
// ❌ ReferenceError: Cannot access 'num' before initialization
console.log(num);
let num = 2;
// ❌ ReferenceError: Cannot access 'name' before initialization
console.log(name);
const name = 'Coding Beauty';
// ❌ ReferenceError: Cannot access 'arr' before initialization
arr = [7, 8, 9];
let arr = [3, 4, 5];
To solve the error, you need to initialize the variable before accessing it.
index.jsCopied!
// ✅ No error
let num = 2;
console.log(num); // 2
// ✅ No error
const name = 'Coding Beauty';
console.log(name); // Coding Beauty
// ✅ No error
let arr = [3, 4, 5];
arr = [7, 8, 9];
var vs let
The occurrence of this error shows an important difference between the var and let keywords. If you had declared the variable with var, the error wouldn’t have occurred.
index.jsCopied!
// No error
console.log(num); // undefined
var num = 2;
// No error
console.log(name); // undefined
var name = 'Coding Beauty';
// No error
arr = [7, 8, 9];
var arr = [3, 4, 5];
This happens because variables declared with the var keyword are hoisted – they are moved by the JavaScript interpreter to the top of the current scope (to the top of the current script or current function).
Basically, this is what happens to our variables declared with var:
index.jsCopied!
var num;
var name;
var arr;
console.log(num); // undefined
num = 2;
console.log(name); // undefined
name = 'Coding Beauty';
arr = [7, 8, 9];
arr = [3, 4, 5];
Note: The declarations are hoisted, but the initializations are not.
Because of this hoisting, even when the variable is declared in a non-function block, like an if block, the error will still not occur if you try to access the variable from outside the if statement.
index.jsCopied!
// No error!
console.log(num); // undefined
if (true) {
var num = 2;
}
Only the global scope and function scopes are used for hoisting, so like before, the variable declaration is moved to the top of the file.
index.jsCopied!
var num;
console.log(num); // undefined
if (true) {
num = 2;
}
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:
Get the window width and height with window.innerWidth and window.innerHeight.
Add an event listener for the resize event on the window object.
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.
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.
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.
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.