Skip to content

Instantly share code, notes, and snippets.

View gragland's full-sized avatar

Gabe Ragland gragland

View GitHub Profile
@gragland
gragland / use-optimistic-mutation-example.ts
Last active May 5, 2024 18:07
useOptimisticMutation for React Query. Optimistically update data in multiple locations with rollback on error.
import axios from 'axios'
import { useOptimisticMutation } from "./useOptimisticMutation.ts"
type Response = boolean
type Error = unknown
type MutationVariables = {itemId: string}
type Items = {id: string; name: string}[]
type Likes = {itemId: string}[]
type History = {type: string}[]
@gragland
gragland / App.js
Last active March 5, 2024 20:05
How to lazy load Firebase with dynamic imports
import getFirebase from "./firebase.js";
function MyApp() {
// Example function that wraps some firebase logic
const onSignup = async (email, password) => {
// Use await to ensure firebase library is loaded
const firebase = await getFirebase();
// Call firebase methods as you normally would
const { user } = await firebase.auth()
.createUserWithEmailAndPassword(email, password);
@gragland
gragland / use-async.jsx
Last active February 17, 2024 16:42
React Hook recipe from https://usehooks.com
import React, { useState, useEffect, useCallback } from 'react';
// Usage
function App() {
const { execute, status, value, error } = useAsync(myFunction, false);
return (
<div>
{status === 'idle' && <div>Start your journey by clicking a button</div>}
{status === 'success' && <div>{value}</div>}
@gragland
gragland / use-require-auth.js
Last active January 27, 2024 16:36
React Hook recipe from https://usehooks.com
import Dashboard from "./Dashboard.js";
import Loading from "./Loading.js";
import { useRequireAuth } from "./use-require-auth.js";
function DashboardPage(props) {
const auth = useRequireAuth();
// If auth is null (still fetching data)
// or false (logged out, above hook will redirect)
// then show loading indicator.
@gragland
gragland / stripe-webhook.js
Last active January 18, 2024 22:20
Next.js Stripe Webhook from divjoy.com
const getRawBody = require("raw-body");
const { updateUserByCustomerId } = require("./_db.js");
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY, {
apiVersion: process.env.STRIPE_API_VERSION,
});
// Disable next.js body parsing (stripe needs the raw body to validate the event)
export const config = {
api: {
@gragland
gragland / App.jsx
Last active November 17, 2023 17:05
Next.js routing to dynamic path without hitting server
'use client'
// ⛔️ DISCLAIMER: This is most likely premature optimization and adds code complexity.
// Only use if you really need to shave off that extra 100-200ms.
function MyComponent({ data }){
return (
<a
href={`/item/${data.id}`}
onClick={(e) => {

A fix for Next.js modals (intercepted routes) not closing when navigating away with <Link> or router.push()

app
├─ @photoModal
│  ├─ (.)photo
|  |  └─ [id]
│  │  |  └─ page.tsx <----- a modal with links to home, /profile, and /login
│  └─ [...catchAll]
│ │ └─ page.tsx &lt;----- returning null here is supposed to cause modal to hide when
import { useState, useCallback, useRef } from "react";
// Usage
function App() {
const [hoverRef, isHovered] = useHover();
return (
<div ref={hoverRef}>
{isHovered ? '😁' : '☹️'}
</div>
import { useState, useEffect } from 'react';
// Usage
function App() {
// Call our hook for each key that we'd like to monitor
const happyPress = useKeyPress('h');
const sadPress = useKeyPress('s');
const robotPress = useKeyPress('r');
const foxPress = useKeyPress('f');
import { useState, useEffect, useRef } from 'react';
// Usage
function App() {
// Ref for the element that we want to detect whether on screen
const ref = useRef();
// Call the hook passing in ref and root margin
// In this case it would only be considered onScreen if more ...
// ... than 300px of element is visible.
const onScreen = useOnScreen(ref, '-300px');