Skip to content

Instantly share code, notes, and snippets.

View samselikoff's full-sized avatar

Sam Selikoff samselikoff

View GitHub Profile

Version 1

import { useActionState } from "react";

async function addToCart(itemId) {
  'use server'

  if (db.add(itemId)) {
    return "success"
[
{
"key": "ctrl+k",
"command": "editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
},
{
"key": "alt+up",
"command": "-editor.action.moveLinesUpAction",
"when": "editorTextFocus && !editorReadonly"
@samselikoff
samselikoff / settings.json
Last active October 31, 2024 08:08
Tweaked Dracula theme for VSCode
{
"diffEditor.renderSideBySide": true,
"editor.fontSize": 14,
"editor.lineHeight": 22,
"editor.tabSize": 2,
"editor.matchBrackets": "never",
"editor.cursorBlinking": "solid",
"editor.selectionHighlight": false,
"editor.occurrencesHighlight": "off",
"editor.scrollbar.horizontal": "hidden",
@samselikoff
samselikoff / git.diff
Created November 21, 2023 14:36
Diff from "Optimistic UI in Remix": https://www.youtube.com/watch?v=d0p95C3Kcsg
diff --git a/app/components/entry-form.tsx b/app/components/entry-form.tsx
index 50e5aeb..84c64fc 100644
--- a/app/components/entry-form.tsx
+++ b/app/components/entry-form.tsx
@@ -1,6 +1,6 @@
-import { useFetcher } from "@remix-run/react";
+import { Form, useSubmit } from "@remix-run/react";
import { format } from "date-fns";
-import { useEffect, useRef } from "react";
+import { useRef } from "react";
@samselikoff
samselikoff / settings.json
Created August 11, 2023 15:53
Dracula customizations using Tailwind Slate
{
"workbench.colorCustomizations": {
"editor.background": "#0f172a",
"menu.background": "#0f172a",
"sideBar.background": "#0b111e",
"banner.background": "#0f172a",
"tab.inactiveBackground": "#0b111e",
"tab.activeBackground": "#0f172a",
"titleBar.activeBackground": "#0b111e",
"editor.lineHighlightBorder": "#ff000000"
import { motion } from "framer-motion";
import { FormEvent, useState } from "react";
import { createGlobalState } from "react-hooks-global-state";
const { useGlobalState } = createGlobalState({
enabled: false,
delay: 1000,
});
@samselikoff
samselikoff / use-state.code-snippets
Last active October 15, 2024 22:27
A VSCode snippet that lets you type `ush` to define some new React state.
{
"Use state": {
"scope": "javascriptreact,typescriptreact",
"prefix": "ush",
"body": [
"let [${1}, set${1/(.*)/${1:/capitalize}/}] = useState($2);",
],
"description": "useState()"
}
}
@samselikoff
samselikoff / range.code-snippets
Last active July 30, 2024 01:37
VSCode snippet for creating a loop of n numbers in JSX! https://twitter.com/samselikoff/status/1611406980639244301
{
"Range of numbers": {
"scope": "javascriptreact,typescriptreact",
"prefix": "range",
"body": [
"{[...Array($1).keys()].map((i) => (",
" <$2 key={i}>",
" $3",
" </$2>",
"))}",

Remix's useFetcher doesn't return a Promise for any of its methods (like fetcher.submit()) because Remix doesn't want you to explicitly await anything so they can handle things like cancellation for you. Instead, they recommend adding a useEffect and performing whatever logic you need to after the fetcher is in a particular state.

I found using an effect to run some logic after a submission to be too indirect, and there seem to be plenty of cases where you want to submit a form and then perform some other work on the client (sometimes async, like requesting the user's permission for their location), and I'd rather just do that after a submission in the event handler rather than an effect.

So here's a proof of concept hook that wraps Remix's useFetcher and returns a version of submit that is a promise, and resolves with the data from the action:

function useFetcherWithPromise() {
  let resolveRef = useRef();
  let promiseRef = useRef();
@samselikoff
samselikoff / chart-with-d3.jsx
Last active May 2, 2024 06:02
Diff from "Building an Animated Line Chart with d3, React and Framer Motion" https://www.youtube.com/watch?v=kPbRDn5Fg0Y
import * as d3 from "d3";
import {
eachMonthOfInterval,
endOfMonth,
format,
isSameMonth,
parseISO,
startOfMonth,
} from "date-fns";
import useMeasure from "react-use-measure";