Categories
React

How to Call a Function with React useEffect Only Once When the Component Mounts?

In many situations, we want to run the useEffect callback only when the component mounts.

In this article, we’ll look at how to call the useEffect callback only when the component mounts.

Pass in an Empty Array into the useEffect Hook

To run the useEffect hook callback only once when the component mounts, we just have to pass in an empty array into the 2nd argument of useEffect hook.

For instance, we can write:

import React, { useEffect } from "react";

export default function App() {
  useEffect(() => {
    console.log("mounted");
  }, []);

  return <div className="App"></div>;
}

We just pass in an empty array into useEffect and the callback would only run once.

So we only see 'mounted' logged when the component is mounted.

We can also move the useEffect hook call into its own function if we use it in multiple places:

import React, { useEffect } from "react";

const useMountEffect = (fun) => useEffect(fun, []);

export default function App() {
  useMountEffect(() => {
    console.log("mounted");
  });

  return <div className="App"></div>;
}

We create the useMountEffect hook that takes the fun function and call useEffect in the function the same way we did before.

Run Code When a Component Unmounts

To run code when a component unmounts, all we have to do is to return a function in the useEffect hook.

For instance, we can write:

import React, { useEffect } from "react";

export default function App() {
  useEffect(() => {
    console.log("mounted");

    return () => {
      console.log("unmounted");
    };
  }, []);

  return <div className="App"></div>;
}

We return a function that logs 'unmounted' .

We’ll see it run when we unmount the component.

Conclusion

To run a function only once when a React component mounts, we just have to pass in an empty array as the 2nd argument of the useEffect hook.

Categories
React

How to Make the React useState Hook Setter Function Reflect Changes Immediately?

Sometimes, we may see that the state changes we made with the useState hook’s state setter function doesn’t reflect at the time we expect them to.

In this article, we’ll look at how to make the React useState hook’s state setter function gets reflected when we want it.

Using the useState State Setter Function Properly

To make sure we pick the latest changes to a state after a usetState state setter function is run, we should watch the latest value of the state with the useEffect hook.

For instance, we can write:

import React, { useEffect, useState } from "react";

export default function App() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log(count);
  }, [count]);

  return (
    <div className="App">
      <button onClick={() => setCount((c) => c + 1)}>increment</button>
      <p>{count}</p>
    </div>
  );
}

We call the useState hook to return the setCount function to set the state.

And we call setCount with a callback that takes the previous state value and return the new state value based on that.

The useEffect callback runs when count ‘s value is changed.

So we can see the latest value of count logged in the useEffect callback.

When we click on the increment button, we show the value of count .

We’ve to use the useEffect hook to watch the state value because React’s useState state setter function is async.

The array we pass in as the 2nd argument of useEffect has the state or prop values we want to watch.

Therefore, we can’t get the value of count right after calling the setCount function.

The state setter function will trigger a re-render when it’s called.

And the latest value of count will be available after the next render.

Conclusion

To get the latest value of a state and do something with it, we’ve to use the useEffect hook with a callback and the array of values we want to watch.

Then in the useEffect callback, we get the latest value of whatever we’re watching.

Categories
Express

How to Let Users Download a File from Node.js Server with Express?

Sometimes, we want to let users download files within our Express app.

In this article, we’ll look at how to let users download files from Express apps.

res.download

One way to let users download a file from a Node.js server is to use the res.download method available with Express.

For instance, we can write:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.get('/download', (req, res) => {
  const file = `${__dirname}/download/foo.txt`;
  res.download(file);
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

We just specify the path to the file with the file string variable.

Then we pass that to the res.download method to download the file.

__dirname is the current working directory of the Express app.

Serve Files as Static Files

We can also use the express.static middleware to serve a folder in our server as a static files folder.

To do this, we write:

const express = require('express')
const app = express()
const port = 3000
app.use('/download', express.static('download'))

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

We call app.use to use the Express static middleware.

The first argument is the path that the user uses to access the static folder’s content.

And the 2nd argument is the Express static middleware.

We create the middleware by calling express.static with the folder path string.

Therefore, we serve the download folder in our server as the static folder.

res.attachment

We can also return a file as a response in our route with the route.attachment method.

It takes the same argument as the res.download method.

It sets the Content-Disposition response header to attachment .

And it also sets the Content-Type response header according to the file type being downloaded.

For instance, we can write:

const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.get('/download', (req, res) => {
  const file = `${__dirname}/download/foo.txt`;
  res.attachment(file).send();
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

We call res.attachment with send to send the file download response to the user.

Conclusion

There’re several ways we can use to let users download files to user’s device via an Express endpoint.

Categories
JavaScript Answers

How to Detect Page Zoom Levels in Modern Browsers?

Sometimes, we may want to detect page zoom levels in modern browsers.

In this article, we’ll look at how to detect zoom levels in modern browsers.

Using the window.devicePixelRatio Property

One way to detect the browser zoom level is to use the window.devicePixelRatio property.

For instance, we can write:

window.addEventListener('resize', () => {
  const browserZoomLevel = Math.round(window.devicePixelRatio * 100);
  console.log(browserZoomLevel)
})

When we zoom in or out, the resize event will be triggered.

So we can listen to it with addEventListener .

In the event handler callback, we get the window.devicePixelRatio which has the ratio between the current pixel size and the regular pixel size.

Divide outerWidth by innerWidth

Since outerWidth is measured in screen pixels and innerWidth is measured in CSS pixels, we can use that to use the ratio between them to determine the zoom level.

For instance, we can write:

window.addEventListener('resize', () => {
  const browserZoomLevel = (window.outerWidth - 8) / window.innerWidth;
  console.log(browserZoomLevel)
})

Then browserZoomLevel is proportional to how much we zoom in or out.

Conclusion

We can detect page zoom levels with the window.devicePixelRatio property or the ratio between the outerWidth and innerWidth .

Categories
JavaScript Answers

How to Convert a JavaScript Object Array to a Hash Map, Indexed by a Property Value of the Object?

Sometimes, we may want to convert a JavaScript objects array into a hash map object with the key of each entry being a property value of the object.

In this article, we’ll look at how to convert a JavaScript object array into a hash map object.

Array.prototype.reduce

The JavaScript array’s reduce method lets us convert an object array into an object easily.

For instance, we can write:

const arr = [{
    key: 'foo',
    val: 'bar'
  },
  {
    key: 'hello',
    val: 'world'
  }
];

const result = arr.reduce((map, obj) => {
  map[obj.key] = obj.val;
  return map;
}, {});

console.log(result)

to do the conversion.

We have an arr object array.

We call reduce to combine the objects in the array, which is obj into the object we return, which is map .

We get the obj.key and set the as a property name of map .

And we use obj.val as the value of obj.key .

The 2nd argument is an empty object, which is the initial value of the reduced result.

As a result, the value of result is:

{foo: "bar", hello: "world"}

Convert the Object Array to a Hash Map with the Map Constructor

We can convert the object array to a hash map with the Map constructor.

For instance, we can write:

const arr = [{
    key: 'foo',
    val: 'bar'
  },
  {
    key: 'hello',
    val: 'world'
  }
];

const result = new Map(arr.map(({
  key,
  val
}) => ([
  key,
  val
])));
console.log(result)

In the map method, we destructure the key and val properties from the parameter object in the callback.

Then we return an array with the key and val inside.

We then pass that to the Map constructor to create a hash map object from it.

And so, result is:

Map(2) {"foo" => "bar", "hello" => "world"}

according to the console log.

Lodash keyBy Method

We can also use the Lodash keyBy method to create the same object in the first example.

For instance, we can write:

const arr = [{
    key: 'foo',
    val: 'bar'
  },
  {
    key: 'hello',
    val: 'world'
  }
];

const result = _.keyBy(arr, o => o.key);
console.log(result)

We just pass in a callback to return the properties that the returned object will have.

The entries of arr will be set as the value of the keys according to the value of the key property.

And so we get:

{
  "foo": {
    "key": "foo",
    "val": "bar"
  },
  "hello": {
    "key": "hello",
    "val": "world"
  }
}

as the value of result .

Object.fromEntries

Another way to create a JavaScript object from an object array is to use the Object.fromEntries method.

For instance, we can write:

const arr = [{
    key: 'foo',
    val: 'bar'
  },
  {
    key: 'hello',
    val: 'world'
  }
];

const result = Object.fromEntries(
  arr.map(({
    key,
    val
  }) => ([
    key,
    val
  ]))
)
console.log(result)

We pass in an array of key-value pair arrays as we did when we try to create a Map instance from the array.

And so we get the same result as the first example for the value of result .

Conclusion

We can use array and object methods that are part of the JavaScript standard library of Lodash to create JavaScript object arrays to objects.