/images/art2.png

Test markdown

Contents

Introduction

This is a test blog post written in Markdown. It demonstrates common features used in blog writing.

test

header 2

header 3

header 4

header 5

list

normal list

  • Easy to write
  • Supports formatting
  • Clean and readable
  • Works with most static site generators

order list

  1. 123123
  2. asdfadsf
  3. lkasdf

Code Example

// Simple JavaScript function
function greet(name) {
  return `Hello, ${name}!`;
}

Features

Clean formatting Blockquotes for every section Inline links like OpenAI Quoted links: 👉 Visit Example Site

React Concurrent

What is React Concurrent?

“Concurrent Features” is a set of rendering capabilities introduced to make React apps more responsive. Instead of blocking the browser until all rendering is done, React can pause, resume, and even abandon a render in progress.

This allows React to:

  • Prioritize urgent updates (e.g., typing) over non-urgent ones (e.g., background data fetch results)
  • Avoid dropping frames during animations or scrolling
  • Keep the UI feeling “alive” even when there’s a lot of work to do

The underlying mechanism is cooperative scheduling — React voluntarily yields control back to the browser when time is up, and continues work later.

Asynchronous in JS

Synchronous & asynchronous

Function run synchronously means code is running as same as your writing.

But in real situation, some code may need time to running (like fetch). If synchronously run all code, program will be block and wait this time consuming part finish and continue.

In the most of the time, You code logic need wait to continue but you don’t want to block all progress. Maybe UI rendering or some other total unrelated code. Unfortunately, JS is single thread langrage and concurrency is not exist. Therefore, you need some technique to some part running asynchronously,

HTML/Document Trick

Understanding offsetWidth, clientWidth, scrollWidth

Note
All these property will round the value to an integer. If you need a fractional value, use element.getBoundingClientRect().

Get Scrollbar width

Reference: https://www.30secondsofcode.org/js/s/get-scrollbar-width/

Get window scroll bar width

const getScrollbarWidth = () =>
    window.innerWidth - document.documentElement.clientWidth;

getScrollbarWidth();

Get a element scroll bar width

const getScrollbarWidth = (el) => {
    const leftBorder = parseInt(
        getComputedStyle(el).getPropertyValue('border-left-width'),
        10
    );
    const rightBorder = parseInt(
        getComputedStyle(el).getPropertyValue('border-right-width'),
        10
    );

    return el.offsetWidth - el.clientWidth - leftBorder - rightBorder;
};

getScrollbarWidth(el);

Element: getBoundingClientRect()

el.getBoundingClientRect() will return: left, top, right, bottom, x, y, width, and height.

Typescript Trick

generic types optional

To make a generic type optional, you have to assign the void as the default value.

const fetchData = <T = void>(url: string): T => {
    const res: T = fetch(url);
    return res;
};

https://garbagevalue.com/blog/optional-generic-typescript#quick-solutions-make-generic-type-optional

string[ ] & [ string, …string[ ] ]

The main difference is that type [string, ...string[]] at least have one element. [] will alert error. string[] could be empty. [] is ok.

ffmpeg

Reference

official

https://ffmpeg.org

blog

https://fireship.io/lessons/ffmpeg-useful-techniques/

node js

https://www.npmjs.com/package/fluent-ffmpeg

example

concatenate

ffmpeg -f concat -i vids.txt -c copy out.mp4

vids.txt:

file 'name1.mov'
file 'name2.mov'
file 'name3.mov'

Type convention

ffmpeg -i in.mp4 out.mov

ffmpeg -i in.mp4 out.gif

Scale

It very common to reduce size of output file. Change scale usually the common and efficient way to do so.

Design Pattern

Design pattern

Factory pattern

const createDataBaseClass = (dbName: DBOption) => {
    switch (dbName) {
        case 'InMemo':
            return InMemoryDataBase;
        case 'SQL':
            return SQL_DB;

        // ...
        // you can add anything else
        default:
            break;
    }
};

Singleton pattern

export const createDataBase = <T extends BaseRecord>() => {
    const db = new InMemoryDataBase<T>();
    return db;
};

const pokemonDB = createDataBase<Pokemon>();

pokemonDB.set({
    id: 'Bulbasaur',
    attack: 59,
    defense: 10,
});

console.log(pokemonDB.get('Bulbasaur'));

// A CPP way to do
const createDataBase2 = <T extends BaseRecord>() => {
    class InMemoryDataBase2 implements DataBase<T> {
        private db: Record<string, T> = {};
        static instance: InMemoryDataBase2 = new InMemoryDataBase2();

        private constructor() {} // private constructor is necessary

        public set(newValue: T): void {
            this.db[newValue.id] = newValue;
        }

        public get(id: string): T | undefined {
            return this.db[id];
        }
    }

    return InMemoryDataBase2;
};
const PokemonDB2 = createDataBase2<Pokemon>();
PokemonDB2.instance.set({
    id: 'Bulbasaur',
    attack: 59,
    defense: 10,
});

Observer (pub/sub) pattern

// ++++++++++  Observer  ++++++++++
const createObserver = <EventType>(): {
    subscribe: (listener: listenerType<EventType>) => () => void; // take listener and return an unsubscribe function
    publish: (event: EventType) => void;
} => {
    let listeners: listenerType<EventType>[] = [];
    return {
        subscribe: (listener: listenerType<EventType>): (() => void) => {
            listeners.push(listener);
            return () => {
                listeners = listeners.filter((l) => l !== listener);
            };
        },
        publish: (event: EventType) => {
            listeners.forEach((l) => l(event));
        },
    };
};

//  +++++++++++++++++++++++++++++

interface BeforeAddValueEvent<T> {
    newValue: T;
    value: T;
}
interface AfterAddValueEvent<T> {
    value: T;
}

class InMemoryDBWithObserver<T extends BaseRecord> extends InMemoryDataBase<T> {
    public set(newValue: T): void {
        this.BeforeAddValueObserver.publish({
            newValue,
            value: this.db[newValue.id],
        });
        this.db[newValue.id] = newValue;
        this.AfterAddValueObserver.publish({
            value: newValue,
        });
    }

    public get(id: string): T | undefined {
        return this.db[id];
    }
    // observer
    private BeforeAddValueObserver = createObserver<BeforeAddValueEvent<T>>();
    private AfterAddValueObserver = createObserver<AfterAddValueEvent<T>>();

    onBeforeAddValue(
        listener: listenerType<BeforeAddValueEvent<T>>
    ): () => void {
        return this.BeforeAddValueObserver.subscribe(listener);
    }

    onAfterAddValue(listener: listenerType<AfterAddValueEvent<T>>): () => void {
        return this.AfterAddValueObserver.subscribe(listener);
    }

    // visiter pattern
    visit(visitor: (item: T) => void): void {
        Object.values(this.db).forEach(visitor);
    }

    // strategy pattern
    getBest(strategy: (item: T) => number): T {
        let findRes: { max: number; res: T | null } = {
            max: -Infinity,
            res: null,
        };

        return Object.values(this.db).reduce((prev, cur) => {
            let score = strategy(cur);
            if (prev.max < score) return { max: score, res: cur };
            return prev;
        }, findRes).res;
    }
}

const pokemonDB = new InMemoryDBWithObserver<Pokemon>();

pokemonDB.onBeforeAddValue((event) => {
    console.log('Before add value');
    console.log(event);
});

const unsubscribe = pokemonDB.onAfterAddValue((event) => {
    console.log('After ADD A Value');
    console.log(event);
});
pokemonDB.onAfterAddValue((event) => {
    console.log('-----------');
});

pokemonDB.set({
    id: 'Bulbasaur',
    attack: 59,
    defense: 10,
});
pokemonDB.set({
    id: 'Bulbasaur',
    attack: 20,
    defense: 30,
});

unsubscribe();

pokemonDB.set({
    id: 'Spinpsaur',
    attack: 159,
    defense: 110,
});

console.log('Visit pattern:');
pokemonDB.visit((item) => console.log(item));

console.log('strategy pattern:');
console.log(pokemonDB.getBest((item) => item.defense));

Adaptor pattern

Typescript overview

type

Union type & Literal type

const add = (
    a: number | string,
    b: number | string,
    type?: 'number' | 'string'
): number | string => {
    if (type === 'string') {
        return a.toString() + b.toString();
    } else return +a + +b;
};

console.log(add(1, 2));

Array

type Book = {
    id: string;
    name: string;
};

let books: Book[] = [];

unknown

let test1: unknown;
let test2: string;

test1 = 'xyz'; // ok
// test2 = test1; // error
function f1(a: any) {
    a.b(); // OK
}
function f2(a: unknown) {
    a.b(); //error
    // Object is of type 'unknown'.
}

Type a Function

type listenerType<EventType> = (event: EventType) => void;

Assign a plain Object

type Primitive = bigint | boolean | null | number | string | symbol | undefined;

type PlainObject = Record<string, Primitive>;
const obj1: PlainObject = { a: 1 }; //âś…
const obj2: PlainObject = { a: 1 }; //❌
const obj3: PlainObject = new myClass(); //❌

Assign a nested plain Object

type Primitive = bigint | boolean | null | number | string | symbol | undefined;

type JSONValue = Primitive | JSONObject | JSONArray;
interface JSONObject {
    [key: string]: JSONValue;
}
interface JSONArray extends Array<JSONValue> {}

const obj1: PlainObject = { a: 1 }; //âś…
const obj2: PlainObject = { a: { b: { c: 3 } } }; //âś…
const obj3: PlainObject = new myClass(); //❌

Type Template arrow function example

export const useFetchAPI = <T extends unknown>(
    url: string,
    method: 'POST' | 'GET',
    body?: string | JSONObject
): [string, T | null] => {
    const [fetchStatus, setFetchStatus] = useState('error');
    const [fetchResult, setFetchResult] = useState<T | null>(null);

    useEffect(() => {
        const apiMockFetch: () => Promise<{
            status: string;
            requestId: string;
            result: T | null;
        }> = () => {
            return new Promise((resolve) => {
                setTimeout(() => {
                    resolve(someData);
                }, 1000);
            });
        };

        const fetchData = async () => {
            const { status, result } = await apiMockFetch();
            setFetchStatus(status);
            if (result !== undefined) {
                setFetchResult(result);
            }
        };
        if (fetchStatus !== 'success') fetchData();
    }, [url, method, body, fetchStatus]);
    return [fetchStatus, fetchResult];
};

Type & interface

type Book = {
    id: string;
    name: string;
};

interface Book {
    id: string;
    name: string;
}

React Logic Reuse Example

React logic extraction

Check this post

Example code

This example demonstrate one single feature using four different feature to archive code split

Code running there: –>Link<–

import { useState, useEffect } from React;

const Styles = {
    redBorder: {
        border: '1px solid #f00',
    },
};

const MouseDisplay = ({ x, y }) => {
    return (
        <div>
            Mouse at x: {x} ; y: {y}
        </div>
    );
};
const MouseDisplay2 = ({ x, y }) => {
    return (
        <div style={{ color: 'teal' }}>
            Mouse at x: {x} ; y: {y}
        </div>
    );
};

// Normal
export const MouseInfoAndDisplay = () => {
    const [x, setX] = useState(0);
    const [y, setY] = useState(0);
    const handleMove = (e) => {
        setX(e.clientX);
        setY(e.clientY);
    };
    return (
        <div style={Styles.redBorder} onMouseMove={handleMove}>
            <MouseDisplay x={x} y={y} />
        </div>
    );
};

// HOC
const withMouseInfo = (Component) => {
    return (props) => {
        const [x, setX] = useState(0);
        const [y, setY] = useState(0);
        const handleMove = (e) => {
            setX(e.clientX);
            setY(e.clientY);
        };
        return (
            <div style={Styles.redBorder} onMouseMove={handleMove}>
                <Component {...props} x={x} y={y} />
            </div>
        );
    };
};

export const HOCMouseDisplay = withMouseInfo(MouseDisplay);
export const HOCMouseDisplay2 = withMouseInfo(MouseDisplay2);

// Render Props

const MouseRenderProps = ({ render }) => {
    const [x, setX] = useState(0);
    const [y, setY] = useState(0);
    const handleMove = (e) => {
        setX(e.clientX);
        setY(e.clientY);
    };

    return (
        <div style={Styles.redBorder} onMouseMove={handleMove}>
            {render(x, y)}
        </div>
    );
};

export const Mouse = () => {
    return (
        <div>
            <MouseRenderProps render={(x, y) => <MouseDisplay x={x} y={y} />} />
            <MouseRenderProps
                render={(x, y) => <MouseDisplay2 x={x} y={y} />}
            />
        </div>
    );
};

// Customize HOOK

const useMouseState = () => {
    const [x, setX] = useState(0);
    const [y, setY] = useState(0);
    const [node, setNode] = useState(null);
    const handleMove = (e) => {
        setX(e.clientX);
        setY(e.clientY);
    };
    useEffect(() => {
        if (node !== null) {
            node.addEventListener('mousemove', handleMove);
        }
    }, [node]);
    return [x, y, setNode];
};

export const MouseUsingHook = () => {
    const [x1, y1, ref1] = useMouseState();
    const [x2, y2, ref2] = useMouseState();

    return (
        <div>
            <div ref={ref1} style={Styles.redBorder}>
                <MouseDisplay x={x1} y={y1} />
            </div>
            <div ref={ref2} style={Styles.redBorder}>
                <MouseDisplay2 x={x2} y={y2} />
            </div>
        </div>
    );
};


const App = () => {
    return (
        <div
            style={{
                display: 'flex',
                flexDirection: 'column',
                height: '100vh',
                justifyContent: 'space-around',
            }}
        >
            <div>
                Normal: <MouseInfoAndDisplay />
            </div>
            <div>
                HOC: <HOCMouseDisplay /> <HOCMouseDisplay2/>
            </div>
            <div>
                Render Props: <Mouse />
            </div>
            <div>
                Hook: <MouseUsingHook />
            </div>
        </div>
    );
};

Useful Post Archive

React

–>Look this post<–

WEB basic

Please Stop Using Local Storage

https://www.rdegges.com/2018/please-stop-using-local-storage/

JWT authentication: When and how to use it

https://blog.logrocket.com/jwt-authentication-best-practices/#:~:text=A%20JWT%20needs%20to%20be,storage%20(or%20session%20storage).

Graphql

Dispatch This: Using Apollo Client 3 as a State Management Solution

https://www.apollographql.com/blog/dispatch-this-using-apollo-client-3-as-a-state-management-solution/

Apollo Client update cache when delete an item from list

https://github.com/apollographql/apollo-client/issues/6451#issuecomment-775242381

Several things for Graphql Security

https://ithelp.ithome.com.tw/articles/10208008

should I put useQuery inside a useEffect and should I store returned data in state?

https://github.com/trojanowski/react-apollo-hooks/issues/158