Skip to content

Instantly share code, notes, and snippets.

View tannerlinsley's full-sized avatar

Tanner Linsley tannerlinsley

View GitHub Profile
@tannerlinsley
tannerlinsley / README.md
Last active April 12, 2024 17:04
Replacing Create React App with the Next.js CLI

Replacing Create React App with the Next.js CLI

How dare you make a jab at Create React App!?

Firstly, Create React App is good. But it's a very rigid CLI, primarily designed for projects that require very little to no configuration. This makes it great for beginners and simple projects but unfortunately, this means that it's pretty non-extensible. Despite the involvement from big names and a ton of great devs, it has left me wanting a much better developer experience with a lot more polish when it comes to hot reloading, babel configuration, webpack configuration, etc. It's definitely simple and good, but not amazing.

Now, compare that experience to Next.js which for starters has a much larger team behind it provided by a world-class company (Vercel) who are all financially dedicated to making it the best DX you could imagine to build any React application. Next.js is the 💣-diggity. It has amazing docs, great support, can grow with your requirements into SSR or static site generation, etc.

So why

@tannerlinsley
tannerlinsley / useBroadcastLeader.ts
Created June 4, 2021 14:37
A React Hook to determine if a tab of your application is the "leader" using BroadcastChannel and leader election
import { BroadcastChannel, createLeaderElection } from 'broadcast-channel'
import React from 'react'
const channels = {}
export function useBroadcastLeader(id = 'default') {
const [isBroadcastLeader, setIsBroadcastLeader] = React.useState(false)
React.useEffect(() => {
if (!channels[id]) {
@tannerlinsley
tannerlinsley / createCrudHooks.js
Created November 29, 2020 06:39
A naive, but efficient starter to generate crud hooks for React Query
export default function createCrudHooks({
baseKey,
indexFn,
singleFn,
createFn,
updateFn,
deleteFn,
}) {
const useIndex = (config) => useQuery([baseKey], indexFn, config)
const useSingle = (id, config) =>
@tannerlinsley
tannerlinsley / onWindowFocus.ts
Last active January 30, 2024 09:37
A utility function to detect window focusing without false positives from iframe focus events
type State = {
added: boolean;
interval: false | ReturnType<typeof setInterval>;
inFrame: boolean;
callbacks: Array<SetFocusedCallback>;
};
type EnrichedHTMLIFrameElement = HTMLIFrameElement & { ___onWindowFocusHandled: boolean };
type SetFocusedCallback = (focused?: boolean) => void;
@tannerlinsley
tannerlinsley / Table.tsx
Last active November 15, 2023 19:53
A quick snippet of an early ReactTable v8 table that renders!
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import { createTable } from 'react-table'
type Row = {
firstName: string
lastName: string
@tannerlinsley
tannerlinsley / Counter.js
Last active September 20, 2023 13:33
Global React State with Context and Immer
import { useCount, useIncrement, useDecrement } from './store.Count'
export default function Counter () {
const count = useCount()
const increment = useIncrement()
const decrement = useDecrement()
return (
<div>
<div>Count: {count}</div>

This middleware does a few interesting things:

  • Ensures a url shape in the zustand store, where we'll store URL information.
  • Assumes we will be storing our url state slice in the ?state search parameter after it has been stringified and base 64 encoded.
  • On creation, decodes stores state from the ?state search parameter into the url slice of our store.
  • After each state update, updates the ?state search parameter with the new url state slice.
  • Sets up an event listener that listens for popstate and re-decodes the state from the URL into our store.
import * as React from 'react'
import * as Plot from '@observablehq/plot'
import useRect from '../hooks/useRect'
import { twMerge } from 'tailwind-merge'
import { useThemeMode } from '../utils/Theme'
import { data } from '../utils/DataColors'
export function ObservablePlot({
legend,
legendType = 'color',
@tannerlinsley
tannerlinsley / remove-linkin-connections.js
Created July 12, 2019 15:43
A script for removing LinkedIn connections automatically
function removeFirstConnection () {
$('[type=ellipsis-horizontal-icon]').first().click()
setTimeout(() => {
$('.js-mn-connection-card__dropdown-delete-btn > button').click()
setTimeout(() => {
$('[data-control-name="confirm_removed"]').click()
}, 250)
}, 250)
}
@tannerlinsley
tannerlinsley / useCalendar.js
Created November 10, 2019 02:25
Calendar Hook
import React from 'react'
import addDays from 'date-fns/add_days'
import isBefore from 'date-fns/is_before'
import isToday from 'date-fns/is_today'
import startOfDay from 'date-fns/start_of_day'
import differenceInCalendarMonths from 'date-fns/difference_in_calendar_months'
export default function useCalendar({
date = new Date(),
offset: userOffset = 0,