Last active: 2 years ago
Custom store with useSyncExternalStore
const Couter = () => {
const { count, info } = useSyncExternalStore(
store.subscribe,
store.getSnapshot
);
return (
<>
<div>
<div>
Count: <span>{count}</span>
</div>
<div>
Info: <span>{info}</span>
</div>
<div>
<Button
onClick={() => store.setState((d) => ({ count: d.count + 1 }))}
>
Last active: 2 years ago
Custom store with useSyncExternalStore
export type State = {
count: number;
info: string;
};
export type Store = {
state: State;
setState: (
stateOrFn: Partial<State> | ((state: State) => Partial<State>)
) => void;
subscribe: (listener: () => void) => () => void;
listeners: Set<() => void>;
getSnapshot: () => State;
};
const store: Store = {
state: {
count: 0,
info: 'Hello',
},
setState(stateOrFn) {
Last active: 2 years ago
Pass props to React children
const childrenWithProps = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
return React.cloneElement(child, {
showContent: child.props.value === currentValue,
});
}
return child;
});
Last active: 2 years ago
Pass props to React children
/**
* Pass onLoad funtion to Suspense child
*/
const childrenWithProps = React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return child;
const demoChild = React.Children.map(
child.props.children as ReactElement<DemoProps>,
(child) => {
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
onLoad: handleChildLoad,
});
}
);
return React.cloneElement(child, {
children: demoChild,
});
});
Last active: 2 years ago
Case request method
import type { NextApiRequest, NextApiResponse } from 'next';
import { Post } from 'types';
import { postLists } from 'lib/posts';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Post[]>
) {
const getPosts = async () => {
const posts = await postLists();
res.status(200).json(posts);
};
switch (req.method) {
case 'GET':
return getPosts();
default:
return res.status(405).end(`Method ${req.method} Not Allowed`);
}
}
Last active: 2 years ago
Play animation on gltf model
const root = gltf.scene;
scene.add(root);
const clock = new THREE.Clock();
const mixer = new THREE.AnimationMixer(root);
gltf.animations.forEach((clip) => {
mixer.clipAction(clip).play();
});
addRenderCallback((time) => {
mixer.update(clock.getDelta());
});
Last active: 2 years ago
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
export function getRandomArbitrary(min: number, max: number) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
export function getRandomInt(min: number, max: number) {
const _min = Math.ceil(min);
const _max = Math.floor(max);
return Math.floor(Math.random() * (_max - _min + 1)) + _min;
}
Last active: 2 years ago
const SpotItem = styled.div<{
min?: number;
max?: number;
}>`
${({ min, max }) =>
min != null &&
max != null &&
css`
animation: 1s ease-in-out 1s infinite alternate spot-scale;
@keyframes spot-scale {
from {
transform: ${`scale(${min})`};
}
to {
transform: ${`scale(${max})`};
}
}
`}
`;
Last active: 2 years ago
fix Git HEAD without a branch
By force pushing the branch to remote, but local HEAD still without a branch.
git push origin HEAD:master --force
A less risky solution would be to create a temporary branch from the detached HEAD, and then merge that branch into master:
git branch temp-branch
git checkout master
git merge temp-branch
git push origin master
Last active: 2 years ago
import pubWorldConfig from '@/libs/pubWorldConfig';
import { NodeInfo, ResUtils, TMat } from '@/show/core';
import { Collapse, Empty, Segmented } from 'antd';
import { SegmentedValue } from 'antd/lib/segmented';
import { lazy, memo, Suspense, useMemo, useState } from 'react';
import Scrollbars from 'react-custom-scrollbars-2';
import * as S from './index.styles';
const { Panel } = Collapse;
const ListItem = lazy(() => import('./ListItem'));
const embedSegment = pubWorldConfig.embedTabs;
const segmentKeys = ['model', 'preset', 'shape', 'text'];
// just hack it. key is one of segmentKeys.
const checkKeys = (key: string): key is 'model' => segmentKeys.includes(key);
type Props = {
embeds: NodeInfo[];
onClickUpdate: (id: string) => void;
onClickRemove: (
Last active: 2 years ago
Generate cubes
import { THREE } from 'lib/hooks/useThree';
function rand(min: number, max?: number) {
if (max === undefined) {
max = min;
min = 0;
}
return min + (max - min) * Math.random();
}
function randomColor() {
return `hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)`;
}
function generateCubes(num = 100, boxWidth = 1, boxHeight = 1, boxDepth = 1) {
const group = new THREE.Group();
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
for (let i = 0; i < num; ++i) {
const material = new THREE.MeshToonMaterial({
Last active: 2 years ago
Override types
type A = {
name: 'a'
age: number
}
type B = {
name: 'b' | A['name']
} & Omit<A, 'name'>
interface A {
name: 'a'
age: number
}
interface B extends Omit<A, 'name'> {
name: 'b' | A['name']
}