Skip to content

Instantly share code, notes, and snippets.

Avatar
🎯
Focusing

Andre andrelandgraf

🎯
Focusing
View GitHub Profile
@andrelandgraf
andrelandgraf / markdown.tsx
Last active Jun 15, 2022
How to process markdown without async code to make it work with server-side React and common-js (e.g. in Remix.run)
View markdown.tsx
/*
* DEPRECATION NOTICE: This workaround is no longer needed. You can now use ESM packages with Remix by
* tracking all ESM packages in your remix.config.js file. This means we can now use react-markdown
* and are not required to reimplement everything from scratch.
* Find a nice example implementation here: https://stackblitz.com/edit/node-ydjuwx?file=remix.config.js
*/
/*
* react-remark does not support cjs anymore but Remix.run will not work with esm just yet (without async imports)
* Unfortunately, the older versions of react-remark do not implement useRemarkSync
@andrelandgraf
andrelandgraf / useLoaderStore.ts
Last active Jun 7, 2022
Wrapper hook for useMatches to quickly access loader data across components in Remix.run
View useLoaderStore.ts
import { useMatches } from 'remix';
// this base hook is used in other hooks to quickly search for specific data across all loaderData using useMatches
// see in action: https://codesandbox.io/s/usematches-loader-data-2h798?file=/app/db.server.ts
export default function useLoaderStore<T>(key: string): T | undefined {
const matchingRoutes = useMatches();
const route = matchingRoutes.find((route) => route.data && route.data[key]);
if (!route || !route.data || route.data[key] === undefined) {
return undefined;
}
@andrelandgraf
andrelandgraf / pre.tsx
Created Dec 26, 2021
PrismJS custom component
View pre.tsx
import​ ​type​ ​{​ ​FC,​ ​HTMLAttributes,​ ​ReactElement​ ​}​ ​from​ ​'react';
import​ ​{​ ​Children​ ​}​ ​from​ ​'react';
import​ ​invariant​ ​from​ ​'tiny-invariant';
import​ ​Highlight,​ ​{​ ​Language,​ ​defaultProps​ ​}​ ​from​ ​'prism-react-renderer';
import​ ​CopyClipboardButton​ ​from​ ​'../button/copyClipboardButton';
function​ ​getLanguageFromClassName(className​: ​string)​ ​{
​  ​const​ ​match​ ​=​ ​className.match(/​language-​(\w+)/);
​  ​return​ ​match​ ? ​match[1]​ : ​'';
@andrelandgraf
andrelandgraf / createSitemap.ts
Last active Jul 3, 2022
sitemap.xml generator for remix.run
View createSitemap.ts
import childProcess from 'child_process';
import fs from 'fs';
import dotenv from 'dotenv';
import prettier from 'prettier';
const rootDir = process.cwd();
dotenv.config({
path: `${rootDir}/.env.production`,
});
@andrelandgraf
andrelandgraf / useErrorNotifications.tsx
Last active Jul 6, 2021
Communication of status / errors codes between client and server via URLSearchParams
View useErrorNotifications.tsx
import { useCallback, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
export default function useErrorNotifications() {
const { pushNotification } = useContext(NotificationsContext);
const [searchParams, setSearchParams] = useSearchParams();
const errorCode = searchParams.get('error');
const onClose = useCallback(() => {
searchParams.delete('error');
@andrelandgraf
andrelandgraf / form.tsx
Last active Dec 28, 2021
working with URLSearchParams in remix.run
View form.tsx
import { Form as RemixForm } from 'remix';
import type { FC } from 'react';
import type { FormProps, Request } from 'remix';
type FormReqBody = { method: 'get' | 'post' | 'put' | 'delete' } & Record<string, string>;
export async function parseURLSearchParams(request: Request): Promise<Partial<FormReqBody>>;
export async function parseURLSearchParams<ReqBody>(request: Request): Promise<Partial<ReqBody & FormReqBody>>;
@andrelandgraf
andrelandgraf / index.js
Last active Jul 29, 2018
working over arrays with for loops in js
View index.js
// summarized and added comments, original source: https://es6.io/ course by Wes Bos
// messing with the prototype
Array.prototype.myFunction = function(){
// add some array functionality
};
// initialising our array
const names = ["Alice", "Foo", "Bar", "Jon Doe"];
// adding some further properties
@andrelandgraf
andrelandgraf / index.js
Last active Jul 30, 2018
working with function expressions and chaining of promises
View index.js
/*
* working with resolve()
*/
const doSomethingChained = (name) => {
console.log('1');
return new Promise((resolve, reject) => setTimeout(() => {console.log(name); resolve();}, 1500, name));
};
doSomethingChained('Alice').then(() => {
console.log('2');
@andrelandgraf
andrelandgraf / index.js
Last active Jul 29, 2018
working with async await
View index.js
/**
* implementing return value of setTimeout() from callback to promise
* @param ms
* @returns {Promise<function>}
*/
const sleep = function (ms) {
// 4.) task 1: we create a new promise and call setTimeout(),
// set timeout creates a new taks 2 that will run after taks 1 has finished & 1500 milliseconds have passed
// new Promise(function(resolve, reject) { ... });
return new Promise(resolve => {
@andrelandgraf
andrelandgraf / index.js
Created Jul 29, 2018
timeout and the event loop
View index.js
/*
* what happens if task 1 takes longer than 1500 milliseconds to be executed? Does task 2 has to wait?
*/
function doSomethingLonger(name, callback){
// 2.) task 1: we execute console.log('1');
console.log('1');
// 3.) task 1: we execute setTimeout. Set timeout creates a new task (task 2) that will be executed in 1500 milliseconds from now on
setTimeout(callback, 1500, name);
// 4.) task 1: we execute console.log('2');
while(true);