Skip to content

Instantly share code, notes, and snippets.

View sergiodxa's full-sized avatar

Sergio Xalambrí sergiodxa

View GitHub Profile
@sergiodxa
sergiodxa / remix-v3-queue-task.tsx
Created October 15, 2025 06:21
An example on how to use `this.queueTask` to run something on every render or on mount
import type { Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
function Component(this: Remix.Handle) {
let isMounted = false;
let renderCount = 0;
// Runs once after first render (setup phase)
this.queueTask(() => {
isMounted = true;
@sergiodxa
sergiodxa / remix-v3-x-tanstack-query.tsx
Created October 12, 2025 04:40
An example on how to use Remix v3 along TanStack Query
import { hydrated, type Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
import {
QueryClient,
QueriesObserver,
type QueryObserverOptions,
} from "@tanstack/query-core";
type Todo = {
userId: number;
@sergiodxa
sergiodxa / counter.tsx
Last active October 12, 2025 00:26
A state helper that simulates useState for Remix v3
import type { Remix } from "@remix-run/dom";
import { press } from "@remix-run/events/press";
import { state } from "./state";
export function Counter(this: Remix.Handle, { initial }: { initial?: number }) {
let [count, setCount] = state(this, initial ?? 0);
return () => (
<button type="button" on={[press(() => setCount((c) => c + 1))]}>
@sergiodxa
sergiodxa / crud.ts
Last active April 21, 2025 04:56
A crud helper for RRv7 routes.ts file
import { index, prefix, route } from "@react-router/dev/routes";
import { camelize, pluralize, singularize } from "inflected";
function createCrud(base = "./views") {
/**
* Create a CRUD route configuration.
* @param name The name of the resource. It will be pluralized for the path.
* @param options The options for the crud.
* @param options.member Extra routes to add to each member.
* @param options.collection Extra routes to add to the collection.
@sergiodxa
sergiodxa / native-create-element.js
Last active March 2, 2025 22:20
Example implementation of the same API of React.createElement but using native DOM elements
// use JSX with el instead of React.createElement
/** @jsx createElement */
const Children = {
only(children) {
if (children.length > 1 || children.length === 0) {
throw new Error('The children must have only one element');
}
return children[0];
}
@sergiodxa
sergiodxa / entry.server.tsx
Last active December 5, 2024 08:05
Dynamically generate a PDF with Remix
import { renderToStream } from "@react-pdf/renderer";
import ReactDOMServer from "react-dom/server";
import { EntryContext, Headers, RemixServer, Request, Response } from "remix";
import PDF, { loader } from "./pdfs/my-pdf.server";
async function handlePDFRequest(request: Request, headers: Headers) {
// get the data for the PDF
let response = await loader({ request, context: {}, params: {} });
// if it's a response return it, this means we redirected
if (response instanceof Response) return response;
@sergiodxa
sergiodxa / react-feature-flags.js
Created October 24, 2019 17:55
React feature flags context, custom hook, hoc and render prop
import React from "react";
const FeatureFlags = React.createContext(null);
export function FeatureProvider({ features = null, children }) {
if (features === null || typeof features !== "object") {
throw new TypeError("The features prop must be an object or an array.");
}
return (
<FeatureFlags.Provider value={features}>{children}</FeatureFlags.Provider>
@sergiodxa
sergiodxa / async-thread.js
Last active June 27, 2023 05:38
Use WebWorkers and promises to run sync heavy functions in a worker (process) and get the result in a promise
function asyncThread(fn, ...args) {
if (!window.Worker) throw Promise.reject(
new ReferenceError(`WebWorkers aren't available.`)
);
const fnWorker = `
self.onmessage = function(message) {
(${fn.toString()})
.apply(null, message.data)
.then(result => self.postMessage(result));
import Auth0 from "@auth/core/providers/auth0";
import { RemixAuth } from "~/services/auth"
import { sessionStorage } from "~/services/session.server";
export let { loader, action } = RemixAuth({
sessionStorage: sessionStorage, // this does nothing yet
secret: process.env.AUTH_SECRET ?? "s3cr3t",
providers: [
Auth0({
@sergiodxa
sergiodxa / persist-inputs-remix-gh-copilot.md
Created October 20, 2022 21:47
An article completely generated by GitHub Copilot based on a title, with just a few minor errors

Persist user inputs after form submit in Remix

This tutorial will show you how to persist user inputs after form submit in Remix.

Prerequisites

Steps