JericaWLancaster

range

Filed under
Snippets
on
in
March 16th, 2023.
Mar 2023.
const range = (start, end, step = 1) => {
  let output = [];

  if (typeof end === 'undefined') {
    end = start;
    start = 0;
  }

  for (let i = start; i < end; i += step) {
    output.push(i);
  }

  return output;
};

Link to this headingContext

Sometimes, you want to render a sequence of numbers. For example, the pagination widget at the bottom of Google search results:

The bottom of Google search results, which shows the numbers 1 through 10 representing the pages of results

Perhaps even more commonly, you want to render something a handful of times. Maybe you want to generate 5 particles, or a bunch of background lines for a graph.

In React, this matter is complicated a bit, because we need an array we can map over. Essentially, I want to be able to do something like this:

const PaginationWidget = () => {
  return (
    <div>
      {range(1, 11).map((num) => (
        <PageNum key={num}>{num}</PageNum>
      ))}
    </div>
  );
};

I'm not able to use a for loop, since we need to render expressions within JSX.

This range utility gives me a concise, functional way to solve for these kinds of problems.

Link to this headingUsage

This utility can be used in several ways.

You can pass a single number, to generate a range from 0 through that number:

range(5); // [0, 1, 2, 3, 4]

You can pass two numbers, to generate a range from start to finish:

range(5, 10); // [5, 6, 7, 8, 9]

Finally, you can pass a third "step" argument, if you want to change the gap between numbers:

range(0, 6, 2); // [0, 2, 4]
range(10, 12, 0.5); // [10, 10.5, 11, 11.5]

You'll notice that the array produced is inclusive of the starting number, but exclusive of the ending number. range(10, 20) includes 10, but does not include 20. This is done intentionally, to match the behaviour of JavaScript methods like slice(opens in new tab).

Link to this headingExplanation

Iterating from a start value to an end value, with a given step, is exactly the problem that for loops were designed to solve. Our range function is really just a thin wrapper around this common "vanilla" pattern!

One possibly surprising bit is this:

if (typeof end === undefined) {
  end = start;
  start = 0;
}

This check exists so that we can call range with a single value, like range(4). Instead of being used as the start value, we're copying this value to end, and setting start to 0. This is a quality-of-life thing, to make it a small bit easier to use.

Last updated on

March 16th, 2023

# of hits