mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 08:11:33 +11:00
prefer regular functions over named arrow functions
This commit is contained in:
parent
12316dbe6a
commit
eb30a7a825
|
@ -1,3 +1,6 @@
|
||||||
{
|
{
|
||||||
"extends": "next/core-web-vitals"
|
"extends": "next/core-web-vitals",
|
||||||
|
"rules": {
|
||||||
|
"func-style": ["error", "declaration", {"allowArrowFunctions": false}]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,12 +32,18 @@ const InnerBlock = styled.div<{ $centered?: boolean }>`
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const ContentBlock: FC<{
|
export function ContentBlock({
|
||||||
|
color = "",
|
||||||
|
children,
|
||||||
|
uncentered = false,
|
||||||
|
}: {
|
||||||
color?: string;
|
color?: string;
|
||||||
uncentered?: boolean;
|
uncentered?: boolean;
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}> = ({ color = "", children, uncentered = false }) => (
|
}) {
|
||||||
<Section $color={color}>
|
return (
|
||||||
<InnerBlock $centered={!uncentered}>{children}</InnerBlock>
|
<Section $color={color}>
|
||||||
</Section>
|
<InnerBlock $centered={!uncentered}>{children}</InnerBlock>
|
||||||
);
|
</Section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -10,9 +10,11 @@ const BacktraceWrapper = styled.section`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getBacktrace = () => window.location.hash.slice(1);
|
function getBacktrace() {
|
||||||
|
return window.location.hash.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
export const BacktraceDisplay: FC = () => {
|
export function BacktraceDisplay() {
|
||||||
const backtrace = useClientValue(getBacktrace) ?? "";
|
const backtrace = useClientValue(getBacktrace) ?? "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -28,4 +30,4 @@ export const BacktraceDisplay: FC = () => {
|
||||||
</button>
|
</button>
|
||||||
</BacktraceWrapper>
|
</BacktraceWrapper>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
|
@ -34,15 +34,15 @@ export function Slider({
|
||||||
}) {
|
}) {
|
||||||
const slider = useRef<HTMLDivElement>(null);
|
const slider = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
|
function handleClick(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
onChange(
|
onChange(
|
||||||
event.nativeEvent.offsetX / (event.target as HTMLDivElement).offsetWidth
|
event.nativeEvent.offsetX / (event.target as HTMLDivElement).offsetWidth
|
||||||
);
|
);
|
||||||
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleDrag = (event: React.MouseEvent<HTMLDivElement>) => {
|
function handleDrag(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
const sliderRef = slider.current;
|
const sliderRef = slider.current;
|
||||||
|
|
||||||
if (!sliderRef || event.buttons !== 1) {
|
if (!sliderRef || event.buttons !== 1) {
|
||||||
|
@ -56,7 +56,7 @@ export function Slider({
|
||||||
const clamped = Math.min(1, Math.max(0, proportion));
|
const clamped = Math.min(1, Math.max(0, proportion));
|
||||||
|
|
||||||
onChange(clamped);
|
onChange(clamped);
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SliderWrapper ref={slider} onClick={handleClick} onMouseMove={handleDrag}>
|
<SliderWrapper ref={slider} onClick={handleClick} onMouseMove={handleDrag}>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
|
||||||
const DefaultBindings = (): KeyBindings => {
|
function DefaultBindings(): KeyBindings {
|
||||||
return {
|
return {
|
||||||
A: "Z",
|
A: "Z",
|
||||||
B: "X",
|
B: "X",
|
||||||
|
@ -14,12 +14,14 @@ const DefaultBindings = (): KeyBindings => {
|
||||||
Left: "LEFT",
|
Left: "LEFT",
|
||||||
Right: "RIGHT",
|
Right: "RIGHT",
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
export const DefaultBindingsSet = (): Bindings => ({
|
export function DefaultBindingsSet(): Bindings {
|
||||||
Actual: DefaultBindings(),
|
return {
|
||||||
Displayed: DefaultBindings(),
|
Actual: DefaultBindings(),
|
||||||
});
|
Displayed: DefaultBindings(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export enum GbaKey {
|
export enum GbaKey {
|
||||||
A = "A",
|
A = "A",
|
||||||
|
@ -69,18 +71,22 @@ export interface Bindings {
|
||||||
Actual: KeyBindings;
|
Actual: KeyBindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toHumanName = (keyName: string) => {
|
function toHumanName(keyName: string) {
|
||||||
return keyName.replace("Arrow", "");
|
return keyName.replace("Arrow", "");
|
||||||
};
|
}
|
||||||
|
|
||||||
export const BindingsControl: FC<{
|
export function BindingsControl({
|
||||||
|
bindings,
|
||||||
|
setBindings,
|
||||||
|
setPaused,
|
||||||
|
}: {
|
||||||
bindings: Bindings;
|
bindings: Bindings;
|
||||||
setBindings: (a: Bindings) => void;
|
setBindings: (a: Bindings) => void;
|
||||||
setPaused: (pause: boolean) => void;
|
setPaused: (pause: boolean) => void;
|
||||||
}> = ({ bindings, setBindings, setPaused }) => {
|
}) {
|
||||||
const [buttonToChange, setButtonToChange] = useState<GbaKey | null>(null);
|
const [buttonToChange, setButtonToChange] = useState<GbaKey | null>(null);
|
||||||
|
|
||||||
const setKey = (key: string) => {
|
function setKey(key: string) {
|
||||||
if (buttonToChange === null) return;
|
if (buttonToChange === null) return;
|
||||||
|
|
||||||
const nextBindings = {
|
const nextBindings = {
|
||||||
|
@ -94,12 +100,12 @@ export const BindingsControl: FC<{
|
||||||
setButtonToChange(null);
|
setButtonToChange(null);
|
||||||
setBindings(nextBindings);
|
setBindings(nextBindings);
|
||||||
setPaused(false);
|
setPaused(false);
|
||||||
};
|
}
|
||||||
|
|
||||||
const onSelectButtonClick = (key: GbaKey) => {
|
function onSelectButtonClick(key: GbaKey) {
|
||||||
setPaused(true);
|
setPaused(true);
|
||||||
setButtonToChange(key);
|
setButtonToChange(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ButtonWrapper onKeyUp={(evt: React.KeyboardEvent) => setKey(evt.key)}>
|
<ButtonWrapper onKeyUp={(evt: React.KeyboardEvent) => setKey(evt.key)}>
|
||||||
|
@ -116,4 +122,4 @@ export const BindingsControl: FC<{
|
||||||
))}
|
))}
|
||||||
</ButtonWrapper>
|
</ButtonWrapper>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ export interface MgbaHandle {
|
||||||
buttonRelease: (key: GbaKey) => void;
|
buttonRelease: (key: GbaKey) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadGame = async (gameUrl: string): Promise<ArrayBuffer> => {
|
async function downloadGame(gameUrl: string): Promise<ArrayBuffer> {
|
||||||
const game = await fetch(gameUrl);
|
const game = await fetch(gameUrl);
|
||||||
|
|
||||||
if (gameUrl.endsWith(".gz")) {
|
if (gameUrl.endsWith(".gz")) {
|
||||||
|
@ -52,7 +52,7 @@ const downloadGame = async (gameUrl: string): Promise<ArrayBuffer> => {
|
||||||
} else {
|
} else {
|
||||||
return await game.arrayBuffer();
|
return await game.arrayBuffer();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export const Mgba = forwardRef<MgbaHandle, MgbaProps>(
|
export const Mgba = forwardRef<MgbaHandle, MgbaProps>(
|
||||||
({ gameUrl, volume, controls, paused }, ref) => {
|
({ gameUrl, volume, controls, paused }, ref) => {
|
||||||
|
|
|
@ -65,11 +65,13 @@ interface MgbaWrapperProps {
|
||||||
setIsPlaying?: (isPlaying: boolean) => void;
|
setIsPlaying?: (isPlaying: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MgbaStandalone: FC<MgbaWrapperProps> = (props) => (
|
export function MgbaStandalone(props: MgbaWrapperProps) {
|
||||||
<AppContainer>
|
return (
|
||||||
<MgbaWrapper {...props} />
|
<AppContainer>
|
||||||
</AppContainer>
|
<MgbaWrapper {...props} />
|
||||||
);
|
</AppContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const MgbaWrapper = forwardRef<MgbaHandle, MgbaWrapperProps>(
|
export const MgbaWrapper = forwardRef<MgbaHandle, MgbaWrapperProps>(
|
||||||
({ gameUrl, isPlaying = true, setIsPlaying }, ref) => {
|
({ gameUrl, isPlaying = true, setIsPlaying }, ref) => {
|
||||||
|
@ -80,10 +82,12 @@ export const MgbaWrapper = forwardRef<MgbaHandle, MgbaWrapperProps>(
|
||||||
|
|
||||||
const [mgbaId, setMgbaId] = useState(0);
|
const [mgbaId, setMgbaId] = useState(0);
|
||||||
|
|
||||||
const setVolume = (newVolume: number) =>
|
function setVolume(newVolume: number) {
|
||||||
setState({ volume: newVolume, bindings });
|
return setState({ volume: newVolume, bindings });
|
||||||
const setBindings = (newBindings: Bindings) =>
|
}
|
||||||
setState({ volume, bindings: newBindings });
|
function setBindings(newBindings: Bindings) {
|
||||||
|
return setState({ volume, bindings: newBindings });
|
||||||
|
}
|
||||||
|
|
||||||
const [paused, setPaused] = useState(false);
|
const [paused, setPaused] = useState(false);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export const useAvoidItchIoScrolling = () => {
|
export function useAvoidItchIoScrolling() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const eventHandler = (e: KeyboardEvent) => {
|
function eventHandler(e: KeyboardEvent) {
|
||||||
if ([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
|
if ([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
window.addEventListener("keydown", eventHandler, false);
|
window.addEventListener("keydown", eventHandler, false);
|
||||||
|
|
||||||
|
@ -14,4 +14,4 @@ export const useAvoidItchIoScrolling = () => {
|
||||||
window.removeEventListener("keydown", eventHandler, false);
|
window.removeEventListener("keydown", eventHandler, false);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
};
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { MutableRefObject, useEffect } from "react";
|
||||||
import { mGBAEmulator } from "./vendor/mgba";
|
import { mGBAEmulator } from "./vendor/mgba";
|
||||||
|
|
||||||
|
|
||||||
export const useFrameSkip = (mgbaModule: MutableRefObject<mGBAEmulator>) => {
|
export function useFrameSkip(mgbaModule: MutableRefObject<mGBAEmulator>) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let previous: number | undefined = undefined;
|
let previous: number | undefined = undefined;
|
||||||
let stopped = false;
|
let stopped = false;
|
||||||
|
@ -11,7 +11,7 @@ export const useFrameSkip = (mgbaModule: MutableRefObject<mGBAEmulator>) => {
|
||||||
let totalTime = 0;
|
let totalTime = 0;
|
||||||
let paused = false;
|
let paused = false;
|
||||||
|
|
||||||
const raf = (time: DOMHighResTimeStamp) => {
|
function raf(time: DOMHighResTimeStamp) {
|
||||||
if (previous) {
|
if (previous) {
|
||||||
const delta = time - previous;
|
const delta = time - previous;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ export const useFrameSkip = (mgbaModule: MutableRefObject<mGBAEmulator>) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.requestAnimationFrame(raf);
|
window.requestAnimationFrame(raf);
|
||||||
return () => { stopped = true; }
|
return () => { stopped = true; };
|
||||||
}, [mgbaModule]);
|
}, [mgbaModule]);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export const useLocalStorage = <T>(
|
export function useLocalStorage<T>(defaultValue: T,
|
||||||
defaultValue: T,
|
appName: string): [T, (newValue: T) => void] {
|
||||||
appName: string
|
|
||||||
): [T, (newValue: T) => void] => {
|
|
||||||
const [value, setValue] = useState(() => {
|
const [value, setValue] = useState(() => {
|
||||||
try {
|
try {
|
||||||
const storageValue = localStorage.getItem(appName);
|
const storageValue = localStorage.getItem(appName);
|
||||||
|
@ -26,4 +24,4 @@ export const useLocalStorage = <T>(
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return [value, setStoredValue];
|
return [value, setStoredValue];
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export const useOnKeyUp = (targetKey: string, callback: () => void) => {
|
export function useOnKeyUp(targetKey: string, callback: () => void) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const downHandler = (evnt: KeyboardEvent) => {
|
function downHandler(evnt: KeyboardEvent) {
|
||||||
if (evnt.key === targetKey) {
|
if (evnt.key === targetKey) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
window.addEventListener("keyup", downHandler);
|
window.addEventListener("keyup", downHandler);
|
||||||
|
|
||||||
|
@ -14,4 +14,4 @@ export const useOnKeyUp = (targetKey: string, callback: () => void) => {
|
||||||
window.removeEventListener("keyup", downHandler);
|
window.removeEventListener("keyup", downHandler);
|
||||||
};
|
};
|
||||||
}, [callback, targetKey]);
|
}, [callback, targetKey]);
|
||||||
};
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const MobileControlsRow = styled.div<{
|
||||||
${(props) => props.$centered && `justify-content: center;`}
|
${(props) => props.$centered && `justify-content: center;`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const useSimpleButton = (mgba: MgbaHandle, button: GbaKey) => {
|
function useSimpleButton(mgba: MgbaHandle, button: GbaKey) {
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
return {
|
return {
|
||||||
onTouchStart: () => {
|
onTouchStart: () => {
|
||||||
|
@ -63,9 +63,9 @@ const useSimpleButton = (mgba: MgbaHandle, button: GbaKey) => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}, [button, mgba]);
|
}, [button, mgba]);
|
||||||
};
|
}
|
||||||
|
|
||||||
const relativeTouch = (touch: Touch) => {
|
function relativeTouch(touch: Touch) {
|
||||||
const target = (touch.target as Element).getBoundingClientRect();
|
const target = (touch.target as Element).getBoundingClientRect();
|
||||||
|
|
||||||
const touchPoint = { x: touch.clientX, y: touch.clientY };
|
const touchPoint = { x: touch.clientX, y: touch.clientY };
|
||||||
|
@ -82,15 +82,15 @@ const relativeTouch = (touch: Touch) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return relativePosition;
|
return relativePosition;
|
||||||
};
|
}
|
||||||
|
|
||||||
const useDpadTouch = (mgba: MgbaHandle) => {
|
function useDpadTouch(mgba: MgbaHandle) {
|
||||||
const [previouslyPressedButtons, setTouchedButtons] = useState<Set<GbaKey>>(
|
const [previouslyPressedButtons, setTouchedButtons] = useState<Set<GbaKey>>(
|
||||||
new Set()
|
new Set()
|
||||||
);
|
);
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const updateDpad = (touches: TouchList) => {
|
function updateDpad(touches: TouchList) {
|
||||||
const currentlyPressed = new Set<GbaKey>();
|
const currentlyPressed = new Set<GbaKey>();
|
||||||
|
|
||||||
for (let touch of touches) {
|
for (let touch of touches) {
|
||||||
|
@ -130,7 +130,7 @@ const useDpadTouch = (mgba: MgbaHandle) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTouchedButtons(currentlyPressed);
|
setTouchedButtons(currentlyPressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onTouchStart: (event: React.TouchEvent) =>
|
onTouchStart: (event: React.TouchEvent) =>
|
||||||
|
@ -141,15 +141,15 @@ const useDpadTouch = (mgba: MgbaHandle) => {
|
||||||
updateDpad(event.nativeEvent.targetTouches),
|
updateDpad(event.nativeEvent.targetTouches),
|
||||||
};
|
};
|
||||||
}, [mgba, previouslyPressedButtons]);
|
}, [mgba, previouslyPressedButtons]);
|
||||||
};
|
}
|
||||||
|
|
||||||
const useAbTouch = (mgba: MgbaHandle) => {
|
function useAbTouch(mgba: MgbaHandle) {
|
||||||
const [previouslyPressedButtons, setTouchedButtons] = useState<Set<GbaKey>>(
|
const [previouslyPressedButtons, setTouchedButtons] = useState<Set<GbaKey>>(
|
||||||
new Set()
|
new Set()
|
||||||
);
|
);
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
const updateAbButtons = (touches: TouchList) => {
|
function updateAbButtons(touches: TouchList) {
|
||||||
const currentlyPressed = new Set<GbaKey>();
|
const currentlyPressed = new Set<GbaKey>();
|
||||||
|
|
||||||
for (let touch of touches) {
|
for (let touch of touches) {
|
||||||
|
@ -173,7 +173,7 @@ const useAbTouch = (mgba: MgbaHandle) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTouchedButtons(currentlyPressed);
|
setTouchedButtons(currentlyPressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
onTouchStart: (event: React.TouchEvent) =>
|
onTouchStart: (event: React.TouchEvent) =>
|
||||||
|
@ -184,9 +184,9 @@ const useAbTouch = (mgba: MgbaHandle) => {
|
||||||
updateAbButtons(event.nativeEvent.targetTouches),
|
updateAbButtons(event.nativeEvent.targetTouches),
|
||||||
};
|
};
|
||||||
}, [mgba, previouslyPressedButtons]);
|
}, [mgba, previouslyPressedButtons]);
|
||||||
};
|
}
|
||||||
|
|
||||||
export const MobileController: FC<{ mgba: MgbaHandle }> = ({ mgba }) => {
|
export function MobileController({ mgba }: { mgba: MgbaHandle }) {
|
||||||
return (
|
return (
|
||||||
<MobileControls onContextMenu={(evt) => evt.preventDefault()}>
|
<MobileControls onContextMenu={(evt) => evt.preventDefault()}>
|
||||||
<MobileControlsRow $size={MobileControlsSize.Small}>
|
<MobileControlsRow $size={MobileControlsSize.Small}>
|
||||||
|
@ -226,4 +226,4 @@ export const MobileController: FC<{ mgba: MgbaHandle }> = ({ mgba }) => {
|
||||||
</MobileControlsRow>
|
</MobileControlsRow>
|
||||||
</MobileControls>
|
</MobileControls>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
|
@ -69,14 +69,16 @@ const ShowOnWideScreen = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const isTouchScreen = () => navigator.maxTouchPoints > 1;
|
function isTouchScreen() {
|
||||||
|
return navigator.maxTouchPoints > 1;
|
||||||
|
}
|
||||||
|
|
||||||
function shouldStartPlaying(isTouchScreen: boolean | undefined) {
|
function shouldStartPlaying(isTouchScreen: boolean | undefined) {
|
||||||
if (isTouchScreen === undefined) return false;
|
if (isTouchScreen === undefined) return false;
|
||||||
return !isTouchScreen;
|
return !isTouchScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MgbaWithControllerSides = () => {
|
function MgbaWithControllerSides() {
|
||||||
const mgba = useRef<MgbaHandle>(null);
|
const mgba = useRef<MgbaHandle>(null);
|
||||||
|
|
||||||
const mgbaHandle = useMemo(
|
const mgbaHandle = useMemo(
|
||||||
|
@ -128,7 +130,7 @@ const MgbaWithControllerSides = () => {
|
||||||
</ShowOnWideScreen>
|
</ShowOnWideScreen>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export const useClientValue = <T,>(fn: () => T) => {
|
export function useClientValue<T>(fn: () => T) {
|
||||||
const [value, setValue] = useState<T>();
|
const [value, setValue] = useState<T>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setValue(fn());
|
setValue(fn());
|
||||||
|
|
Loading…
Reference in a new issue