By using ReturnType
we don't have to manually write type for Context
See also gist for SolidJS https://gist.github.com/JLarky/a46055f673a2cb021db1a34449e3be07
And original tweet https://twitter.com/JLarky/status/1554152932425117697
type AnyFunction = (...args: any[]) => any | |
function useEvent<T extends AnyFunction>(callback?: T) { | |
const ref = useRef<AnyFunction | undefined>(() => { | |
throw new Error("Cannot call an event handler while rendering.") | |
}) | |
// Or useInsertionEffect if it's React 18 | |
useLayoutEffect(() => { | |
ref.current = callback | |
}) |
import { sample } from 'lodash'; | |
import React from 'react'; | |
import cookie from 'cookie'; | |
import Layout from '../components/layout'; | |
import HomeV1 from '../components/scenes/home/v1'; | |
import HomeV2 from '../components/scenes/home/v2'; | |
const EXPERIMENT_OPTIONS = { | |
v1: HomeV1, | |
v2: HomeV2, |
import React from 'react'; | |
import GatsbyImage from 'gatsby-image'; | |
import PropTypes from 'prop-types'; | |
const Image = ({ objectFit, objectPosition, ...rest }) => { | |
let wrapperStyles = {}; | |
let imageStyles = {}; | |
if (objectFit === 'contain') { | |
wrapperStyles.width = '100%'; |
@tailwind base; | |
/* | |
* Oldschool, top left anchored repeating backgrounds should be opt-in instead | |
* of opt-out in 2022, lol. | |
*/ | |
*, | |
*::before, | |
*::after { | |
min-width: 0; |
By using ReturnType
we don't have to manually write type for Context
See also gist for SolidJS https://gist.github.com/JLarky/a46055f673a2cb021db1a34449e3be07
And original tweet https://twitter.com/JLarky/status/1554152932425117697
gatsby-config.js
first.require('ts-node').register()
which registers a TypeScript evaluator that will be used when Gatsby
reads all other API Javascript files. In other words, we only need to do
this once in our entire codebase and not in other Gatsby files like
gatsby-node.js
.gatsby-config.js
re-exports all the exported variables available
in gatsby-config.ts
.Memoization is a somewhat fraught topic in the React world, meaning that it's easy to go wrong with it, for example, by [making memo()
do nothing][memo-pitfall] by passing in children to a component. The general advice is to avoid memoization until the profiler tells you to optimize, but not all use cases are general, and even in the general use case you can find tricky nuances.
Discussing this topic requires some groundwork about the technical terms, and I'm placing these in once place so that it's easy to skim and skip over:
Mute these words in your settings here: https://twitter.com/settings/muted_keywords | |
ActivityTweet | |
generic_activity_highlights | |
generic_activity_momentsbreaking | |
RankedOrganicTweet | |
suggest_activity | |
suggest_activity_feed | |
suggest_activity_highlights | |
suggest_activity_tweet |
const sanityClient = require('@sanity/client'); | |
const crypto = require('crypto'); | |
const { | |
SANITY_API_TOKEN, | |
SANITY_PROJECT_ID, | |
SANITY_DATASET, | |
SHOPIFY_SECRET | |
} = process.env; |
const { createHttpLink } = require('apollo-link-http'); | |
const fetch = require('node-fetch'); | |
const store = require('store'); | |
const sourceNodes = require('gatsby/dist/utils/source-nodes'); | |
require('dotenv').config(); | |
const craftGqlUrl = process.env.CRAFT_GQL_URL; | |
const craftGqlToken = process.env.CRAFT_GQL_TOKEN; | |
module.exports = { |