Categories
JavaScript Answers

How to Format Numbers by Prepending a 0 to Single-Digit Numbers in JavaScript?

Sometimes, we may want to format our numbers by pretending zeroes before it until it matches a given length.

In this article, we’ll look at how to format numbers by padding a number with leading zeroes until it meets a given length.

Number.prototype.toLocaleString

One way to pad a number with leading zeroes is to use the toLocaleString method.

It lets us pad a number with leading zeroes until it reaches a minimum length.

For instance, we can write:

const formattedNumber = (2).toLocaleString('en-US', {
  minimumIntegerDigits: 2,
  useGrouping: false
})
console.log(formattedNumber)

To pad the number 2 with leading zeroes until it’s 2 digits long.

minimumIntegerDigits is set to 2 so that the returned number string will be at least 2 characters long.

useGrouping set to false removes any digit grouping separator for the given locale.

Therefore, formattedNumber is '02' .

Write Our Own Function

We can also write our own function to pad a number string until it meets the given length.

For instance, we can write:

function leftPad(number, targetLength) {
  let output = number.toString();
  while (output.length < targetLength) {
    output = '0' + output;
  }
  return output;
}

const formattedNumber = leftPad(2, 2)
console.log(formattedNumber)

We create the leftPad function that takes the number to format and the targetLength to pad to as arguments.

We convert the number to a string with the toString method and assign it to output.

Then we use a while loop to prepend the output with zeroes until the targetLength is met.

Then we return the output string.

So when we call leftPad with 2 and 2, we get '02' .

String.prototype.padStart

Another way to pad a number string with zeroes until a given length is to use the string padStart method.

For instance, we can write:

const formattedNumber = (2).toString().padStart(2, "0");
console.log(formattedNumber)

We call toString on 2 to convert it to a string.

Then we call padStart on it with the length that we want to pad to and the character to pad the string with.

padStart prepends the string with the characters in the 2nd argument repeatedly until the length in the first argument is met.

Therefore, formattedNumber is the same as the other examples.

Conclusion

We can format numbers with leading zeroes until it meets a given length with JavaScript with a few simple methods or operations.

Categories
React

Making HTTP Requests with React Query — Async Mutations and Invalidate Requests

The React Query library lets us make HTTP requests easily in our React apps.

In this article, we’ll look at how to make HTTP requests with React Query.

mutateAsync

The mutateAsync method lets us call mutate is an async manner.

It returns a promise which lets us commit our mutation request in an async manner, which doesn’t hold up the JavaScript main thread.

For instance, we can write:

import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-query";

export default function App() {
  const { reset, mutateAsync } = useMutation((data) =>
    axios.post("https://jsonplaceholder.typicode.com/posts", data)
  );
  const [title, setTitle] = useState("");

  const onCreateTodo = async (e) => {
    e.preventDefault();
    try {
      const todo = await mutateAsync({
        title
      });
      console.log(todo);
    } catch (error) {
      console.log(error);
    } finally {
      console.log("done");
    }
  };

  return (
    <div>
      <form onSubmit={onCreateTodo}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <br />
        <button type="submit">Create Todo</button>
        <button type="button" onClick={() => reset()}>
          reset
        </button>
      </form>
    </div>
  );
}

We call mutateAsync which returns a promise with the response data from the axios.post call.

Retry Mutations

With React Query, we can easily retry our mutation HTTP request if it returns an error.

We just have to set the retry option to the number of times we want to retry.

For instance, we can write:

import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-query";

export default function App() {
  const { reset, mutateAsync } = useMutation(
    (data) => axios.post("https://jsonplaceholder.typicode.com/posts", data),
    {
      retry: 3
    }
  );
  const [title, setTitle] = useState("");

  const onCreateTodo = async (e) => {
    e.preventDefault();
    try {
      const todo = await mutateAsync({
        title
      });
      console.log(todo);
    } catch (error) {
      console.log(error);
    } finally {
      console.log("done");
    }
  };

  return (
    <div>
      <form onSubmit={onCreateTodo}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <br />
        <button type="submit">Create Todo</button>
        <button type="button" onClick={() => reset()}>
          reset
        </button>
      </form>
    </div>
  );
}

We call the useMutation hook with an object that has the retry property set to 3 to retry up to 3 times if the mutation request fails.

Invalidate Queries

We can invalidate queries so we can mark a query request as stale and make the request again automatically.

For instance, we can write:

index.js

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import App from "./App";

const queryClient = new QueryClient();
queryClient.invalidateQueries("yesNo", { exact: true });

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <StrictMode>
      <App />
    </StrictMode>
  </QueryClientProvider>,
  rootElement
);

App.js

import axios from "axios";
import React from "react";
import { useQuery } from "react-query";
export default function App() {
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"));

  return <div>{JSON.stringify(data)}</div>;
}

We call:

queryClient.invalidateQueries("yesNo", { exact: true });

to invalidate the query by the key.

exact set to true means the key of the query request must match exactly before it’s invalidated.

Conclusion

We run mutation requests asynchronously and invalidate query requests to make the request again with Reacr Query.

Categories
React

Making HTTP Requests with React Query — Mutation Side Effects

The React Query library lets us make HTTP requests easily in our React apps.

In this article, we’ll look at how to make HTTP requests with React Query.

Mutation Side Effects

We can watch for events that are emitted when mutations are being committed.

For instance, we can write:

import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-query";

export default function App() {
  const { reset, mutate } = useMutation(
    (data) => axios.post("https://jsonplaceholder.typicode.com/posts", data),
    {
      onMutate: (variables) => {
        console.log(variables);
        return {};
      },
      onError: (error, variables, context) => {
        console.log(error, variables, context);
      },
      onSuccess: (data, variables, context) => {
        console.log(data, variables, context);
      },
      onSettled: (data, error, variables, context) => {
        console.log(data, error, variables, context);
      }
    }
  );
  const [title, setTitle] = useState("");

  const onCreateTodo = (e) => {
    e.preventDefault();
    mutate({
      title
    });
  };

  return (
    <div>
      <form onSubmit={onCreateTodo}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <br />
        <button type="submit">Create Todo</button>
        <button type="button" onClick={() => reset()}>
          reset
        </button>
      </form>
    </div>
  );
}

The onMutate method is run when the mutation request is being made.

variables has the mutation data from the data parameter.

onError is run when there’s an error with the mutation.

error has the error object.

variables is the same as before.

context has the context data which has the mutation request data.

onSuccess is run when the mutation request is successful.

data has the mutation response data.

variables and context are the same as the other callback parameters.

onSettled is run whenever a mutation request is finished regardless of whether it’s successful or not.

All the parameters are the same as before.

We can also add the same callbacks to the mutate method call.

For instance, we can write:

import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-query";

export default function App() {
  const { reset, mutate } = useMutation(
    (data) => axios.post("https://jsonplaceholder.typicode.com/posts", data),
    {
      onMutate: (variables) => {
        console.log(variables);
        return {};
      },
      onError: (error, variables, context) => {
        console.log(error, variables, context);
      },
      onSuccess: (data, variables, context) => {
        console.log(data, variables, context);
      },
      onSettled: (data, error, variables, context) => {
        console.log(data, error, variables, context);
      }
    }
  );
  const [title, setTitle] = useState("");

  const onCreateTodo = (e) => {
    e.preventDefault();
    mutate(
      {
        title
      },
      {
        onMutate: (variables) => {
          console.log(variables);
          return {};
        },
        onError: (error, variables, context) => {
          console.log(error, variables, context);
        },
        onSuccess: (data, variables, context) => {
          console.log(data, variables, context);
        },
        onSettled: (data, error, variables, context) => {
          console.log(data, error, variables, context);
        }
      }
    );
  };

  return (
    <div>
      <form onSubmit={onCreateTodo}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <br />
        <button type="submit">Create Todo</button>
        <button type="button" onClick={() => reset()}>
          reset
        </button>
      </form>
    </div>
  );
}

The callbacks we add to the object we pass in as the 2nd argument of mutate will run after the callbacks we added to the useMutation hook.

Conclusion

We can add callbacks to the object we pass into the useMutation hook or mutate method to watch for any events that are triggered when making our mutation request with React Query.

Categories
React

Making HTTP Requests with React Query — Mutations

The React Query library lets us make HTTP requests easily in our React apps.

In this article, we’ll look at how to make HTTP requests with React Query.

Mutations

Mutations let us make HTTP requests to change data on a server by creating, updating, and deleting them.

For instance, we can write:

index.js

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { QueryClient, QueryClientProvider } from "react-query";
import App from "./App";

const queryClient = new QueryClient();

const rootElement = document.getElementById("root");
ReactDOM.render(
  <QueryClientProvider client={queryClient}>
    <StrictMode>
      <App />
    </StrictMode>
  </QueryClientProvider>,
  rootElement
);

App.js

import axios from "axios";
import React from "react";
import { useMutation } from "react-query";

export default function App() {
  const { mutate, isLoading, isError, isSuccess } = useMutation((data) =>
    axios.post("https://jsonplaceholder.typicode.com/posts", data)
  );

  return (
    <div>
      <div>{isLoading && "loading"}</div>
      <div>{isError && "error"}</div>
      <div>{isSuccess && "success"}</div>
      <button
        onClick={() => {
          mutate({
            title: "foo",
            body: "bar",
            userId: 1
          });
        }}
      >
        Add Todo
      </button>
    </div>
  );
}

We call the useMutation hook with a callback that lets us make a POST request to the API to submit some data.

The callback should return a promise.

The request payload is stored in the payload parameter.

The hook returns the mutate function that lets us make the request.

isLoading is true when the request is loading.

isError is true when a request fails.

isSuccess is true when the request is successfully completed.

Alternatively, we can replace isLoading , isSuccess , and isError with the status property:

import axios from "axios";
import React from "react";
import { useMutation } from "react-query";

export default function App() {
  const { mutate, status } = useMutation((data) =>
    axios.post("https://jsonplaceholder.typicode.com/posts", data)
  );

  return (
    <div>
      <div>{status === "loading" && "loading"}</div>
      <div>{status === "error" && "error"}</div>
      <div>{status === "success" && "success"}</div>
      <button
        onClick={() => {
          mutate({
            title: "foo",
            body: "bar",
            userId: 1
          });
        }}
      >
        Add Todo
      </button>
    </div>
  );
}

'loading' status is the status when the request is loading.

'error' status is the status when the request has an error.

'success' status is the status when the request is successful.

Resetting Mutation State

We can clear the mutation request state after the request is done.

To do this, we can call the reset method:

import axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-query";

export default function App() {
  const { reset, mutate } = useMutation((data) =>
    axios.post("https://jsonplaceholder.typicode.com/posts", data)
  );
  const [title, setTitle] = useState("");

  const onCreateTodo = (e) => {
    e.preventDefault();
    mutate({
      title
    });
  };

  return (
    <div>
      <form onSubmit={onCreateTodo}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <br />
        <button type="submit">Create Todo</button>
        <button type="button" onClick={() => reset()}>
          reset
        </button>
      </form>
    </div>
  );
}

We call the reset method when we click on the reset the state returned by the useMutation hook.

Conclusion

We can make requests that change data on the server with the React Query useMutation hook.

Categories
React

Making HTTP Requests with React Query — Placeholder Data, Initial Data, and Prefetching

The React Query library lets us make HTTP requests easily in our React apps.

In this article, we’ll look at how to make HTTP requests with React Query.

Placeholder Data

We can add placeholder data that are set when the request is loading.

To do this, we set the placeholderData property by writing:

import axios from "axios";
import React from "react";
import { useQuery } from "react-query";
export default function App() {
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"), {
    placeholderData: {}
  });

  return <div>{JSON.stringify(data)}</div>;
}

We can also load placeholder data from the cache.

To do this, we write:

import axios from "axios";
import React from "react";
import { useQuery, useQueryClient } from "react-query";
export default function App() {
  const queryClient = useQueryClient();
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"), {
    placeholderData: () => {
      return queryClient.getQueryData("yesNo");
    }
  });

  return <div>{JSON.stringify(data)}</div>;
}

We get the cached data with the queryClient.getQueryData method with the identifier of the request.

Initial Query Data

Also, we can set initial query data that are set when the query is first made.

To do this, we write:

import axios from "axios";
import React from "react";
import { useQuery } from "react-query";
export default function App() {
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"), {
    initialData: {}
  });

  return <div>{JSON.stringify(data)}</div>;
}

We can also set the amount of time in milliseconds that the data is considered fresh with the staleTime property.

To do this, we write:

import axios from "axios";
import React from "react";
import { useQuery } from "react-query";
export default function App() {
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"), {
    initialData: {},
    staleTime: 1000
  });

  return <div>{JSON.stringify(data)}</div>;
}

We set stateTime to 1000 milliseconds to invalidate the initial data after that time.

We can also set initialData to a function to only set the initial data when the query is first made:

import axios from "axios";
import React from "react";
import { useQuery } from "react-query";
export default function App() {
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"), {
    initialData: () => {
      return {};
    }
  });

  return <div>{JSON.stringify(data)}</div>;
}

Prefetching

React Query lets us prefetch data.

For instance, we can write:

import axios from "axios";
import React, { useEffect } from "react";
import { useQuery, useQueryClient } from "react-query";
export default function App() {
  const queryClient = useQueryClient();
  const { data } = useQuery("yesNo", () => axios("https://yesno.wtf/api"));

  const prefetch = async () => {
    await queryClient.prefetchQuery("yesNo", () => Promise.resolve({}));
  };

  useEffect(() => {
    prefetch();
  }, []);

  return <div>{JSON.stringify(data)}</div>;
}

to call queryClient.prefetchQuery to prefetch the response for the request with identifier 'yesNo' .

Conclusion

We can prefetch data, set placeholder data, and set initial data for our requests with React Query.