Skip to content

Instantly share code, notes, and snippets.


Michael Jackson mjackson

View GitHub Profile
mjackson / download-counts.mjs
Last active November 11, 2022 05:43
Download counts for react-router
View download-counts.mjs
const npmApiUrl = "";
async function fetchDownloadCounts(packageName, year) {
let range = `${year}-01-01:${year}-12-31`;
let response = await fetch(`${npmApiUrl}/${range}/${packageName}`);
return (await response.json()).downloads;
async function getDownloads(startYear, endYear = startYear) {
if (endYear < startYear) {
mjackson /
Last active April 27, 2023 00:11
Notes on route composition in React Router v6, along with a suggested improvement you can make today to start upgrading

Composing <Route> in React Router v6

Composition of <Route> elements in React Router is changing in v6 from how it worked in v4/5 and in Reach Router. React Router v6 is the successor of both React Router v5 and Reach Router.

This document explains our rationale for making the change as well as a pattern you will want to avoid in v6 and a note on how you can start preparing your v5 app for v6 today.


In React Router v5, we had an example of how you could create a element]( to restrict access to certain routes on the page. This element was a simple [wrapper around an actual element that made a simple decision: is the user authenticated or not? If so, ren

mjackson /
Last active May 23, 2023 12:42
Notes on handling redirects in React Router v6, including a detailed explanation of how this improves on what we used to do in v4/5

Redirects in React Router v6

An important part of "routing" is handling redirects. Redirects usually happen when you want to preserve an old link and send all the traffic bound for that destination to some new URL so you don't end up with broken links.

The way we recommend handling redirects has changed in React Router v6. This document explains why.


In React Router v4/5 (they have the same API, you can read about why we had to bump the major version here) we had a <Redirect> component that you could use to tell the router when to automatically redirect to another URL. You might have used it like this:

View useColorSchemePreference.ts
import React from "react";
export type ColorScheme = "light" | "dark";
export default function useColorSchemePreference(
defaultColorScheme: ColorScheme = "light"
) {
let darkQuery = "(prefers-color-scheme: dark)";
let [colorScheme, setColorScheme] = React.useState<ColorScheme>(
typeof window === "object" && window.matchMedia
View react-preload-example.js
import React from 'react';
let DataContext = React.createContext();
// A higher-order component for pairing preload function + component ...
function withData(preloadData, Component, autoPreloadOnRender = true) {
let needsPreload = !!autoPreloadOnRender;
let promise;
let value;
View renderFeed.js
let feed = {
type: 'rss',
props: {
'xmlns:blogChannel': 'https://...',
version: '2.0',
children: [
type: 'channel',
props: {
title: 'Remix Blog',
View useControl.js
function useControl(defaultValue, value, onChange) {
let [localValue, setLocalValue] = React.useState(defaultValue)
let isControlled = value != null // the key
let activeValue = isControlled ? value : localValue
let setActiveValue = nextValue => {
if (isControlled) {
if (onChange) {
} else {
View expect-element.js
toContainElement(instance, targetElement) {
let matchingElements = instance.findAllByProps(targetElement.props);
if (matchingElements.length === 0) {
return {
message() {
let props = JSON.stringify(targetElement.props);
return `expected to find element with props ${props}`;
View react-router-lazy.js
import React from 'react';
import { lazy } from 'react-suspense-resource';
let Courses = lazy(() => import('./Courses.js'));
let CoursesIndex = lazy(() => import('./CoursesIndex.js'));
let routes = [
path: "courses",
element: <Courses />,
View routes.js
let routes = (
<RankedSwitch> picks the best child <Route> that matches
the path. Like <Switch>, it does not match deeply, so you
need to use /* on the path if you want to do that. Like
@reach/router's <Router>, it ranks the paths so you don't
have to think about ordering.
Con: You have to use /* to do deep matching