Skip to content

Commit 086cff0

Browse files
test: test that functions have the same reference
1 parent 6510511 commit 086cff0

7 files changed

Lines changed: 101 additions & 6 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/example-nextjs14/src/app/Form-for-test.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useSearchParams } from 'next/navigation';
33
import React from 'react';
44
import { Field, Input, RefreshButton, Tag } from 'shared/components';
55
import { form } from 'shared/form';
6+
import { usePrevious } from 'shared/usePrevious';
67
import { useUrlState } from 'state-in-url/next';
78

89
export const Form = ({
@@ -52,8 +53,8 @@ export const Form = ({
5253
reset()
5354
reset({ replace: false, scroll: true })
5455
}
55-
// eslint-disable-next-line react-hooks/exhaustive-deps
56-
}, []);
56+
}, [setUrl, setState, urlState, reset]);
57+
5758
const onChangeAge = React.useCallback(
5859
(ev: React.ChangeEvent<HTMLInputElement>) => {
5960
const val = +ev.target.value;
@@ -89,6 +90,20 @@ export const Form = ({
8990
[setUrl],
9091
);
9192

93+
// same reference
94+
const setUrlStable = React.useRef(setUrl);
95+
const setUrlPrev = usePrevious(setUrl);
96+
const setStatePrev = usePrevious(setState);
97+
const setStateStable = React.useRef(setState);
98+
99+
const [isError, setIsError] = React.useState(false);
100+
const isInit = setUrlPrev
101+
const isEqual = (setUrlStable.current !== setUrlPrev || setUrlPrev !== setUrl || setStateStable.current !== setState || setStatePrev !== setState)
102+
if (isInit && isEqual && !isError) {
103+
setIsError(true)
104+
}
105+
if (isError) return null;
106+
92107
return (
93108
<div className={className}>
94109
<div className="flex-1 border border-grey rounded-md p-4 shadow-md">

packages/example-nextjs15/src/app/Form-for-test.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React from 'react';
44
import { Field, Input, RefreshButton, Tag } from 'shared/components';
55
import { form } from 'shared/form';
66
import { useUrlState } from 'state-in-url/next';
7+
import { usePrevious } from 'shared/usePrevious';
78

89
export const Form = ({
910
className,
@@ -50,8 +51,8 @@ export const Form = ({
5051
reset()
5152
reset({ replace: false, scroll: true })
5253
}
53-
// eslint-disable-next-line react-hooks/exhaustive-deps
54-
}, []);
54+
}, [reset, setState, setUrl, urlState]);
55+
5556
const onChangeAge = React.useCallback(
5657
(ev: React.ChangeEvent<HTMLInputElement>) => {
5758
const val = +ev.target.value;
@@ -86,6 +87,20 @@ export const Form = ({
8687
[setUrl],
8788
);
8889

90+
// same reference
91+
const setUrlStable = React.useRef(setUrl);
92+
const setUrlPrev = usePrevious(setUrl);
93+
const setStatePrev = usePrevious(setState);
94+
const setStateStable = React.useRef(setState);
95+
96+
const [isError, setIsError] = React.useState(false);
97+
const isInit = setUrlPrev
98+
const isEqual = (setUrlStable.current !== setUrlPrev || setUrlPrev !== setUrl || setStateStable.current !== setState || setStatePrev !== setState)
99+
if (isInit && isEqual && !isError) {
100+
setIsError(true)
101+
}
102+
if (isError) return null;
103+
89104
return (
90105
<div className={className}>
91106
<div className="flex-1 border border-grey rounded-md p-4 shadow-md">

packages/example-react-router6/src/Form-for-test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { useSearchParams } from "react-router-dom";
33
import { Field, Input, RefreshButton, Tag } from "shared/components";
44
import { form } from "shared/form";
5+
import { usePrevious } from "shared/usePrevious";
56
import { useUrlState } from "state-in-url/react-router6";
67

78
export const Form = ({ className }: { className?: string }) => {
@@ -78,6 +79,24 @@ export const Form = ({ className }: { className?: string }) => {
7879
[setUrl],
7980
);
8081

82+
// same reference
83+
const setUrlStable = React.useRef(setUrl);
84+
const setUrlPrev = usePrevious(setUrl);
85+
const setStatePrev = usePrevious(setState);
86+
const setStateStable = React.useRef(setState);
87+
88+
const [isError, setIsError] = React.useState(false);
89+
const isInit = setUrlPrev;
90+
const isEqual =
91+
setUrlStable.current !== setUrlPrev ||
92+
setUrlPrev !== setUrl ||
93+
setStateStable.current !== setState ||
94+
setStatePrev !== setState;
95+
if (isInit && isEqual && !isError) {
96+
setIsError(true);
97+
}
98+
if (isError) return null;
99+
81100
return (
82101
<div className={className}>
83102
<div className="flex-1 border border-grey rounded-md p-4 shadow-md">

packages/example-react-router7/src/Form-for-test.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { useSearchParams } from "react-router";
33
import { Field, Input, RefreshButton, Tag } from "shared/components";
44
import { form } from "shared/form";
5+
import { usePrevious } from "shared/usePrevious";
56
import { useUrlState } from "state-in-url/react-router";
67

78
export const Form = ({ className }: { className?: string }) => {
@@ -78,6 +79,24 @@ export const Form = ({ className }: { className?: string }) => {
7879
[setUrl],
7980
);
8081

82+
// same reference
83+
const setUrlStable = React.useRef(setUrl);
84+
const setUrlPrev = usePrevious(setUrl);
85+
const setStatePrev = usePrevious(setState);
86+
const setStateStable = React.useRef(setState);
87+
88+
const [isError, setIsError] = React.useState(false);
89+
const isInit = setUrlPrev;
90+
const isEqual =
91+
setUrlStable.current !== setUrlPrev ||
92+
setUrlPrev !== setUrl ||
93+
setStateStable.current !== setState ||
94+
setStatePrev !== setState;
95+
if (isInit && isEqual && !isError) {
96+
setIsError(true);
97+
}
98+
if (isError) return null;
99+
81100
return (
82101
<div className={className}>
83102
<div className="flex-1 border border-grey rounded-md p-4 shadow-md">

packages/example-remix2/app/routes/Form-for-test.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useSearchParams } from "react-router-dom";
33
import { Field, Input, RefreshButton, Tag } from "../../../shared/components";
44
import { form } from "../../../shared/form";
55
import { useUrlState } from "state-in-url/remix";
6+
import { usePrevious } from "../../../shared/usePrevious";
67

78
export const Form = ({ className }: { className?: string }) => {
89
const [sp] = useSearchParams();
@@ -78,6 +79,21 @@ export const Form = ({ className }: { className?: string }) => {
7879
[setUrl],
7980
);
8081

82+
83+
// same reference
84+
const setUrlStable = React.useRef(setUrl);
85+
const setUrlPrev = usePrevious(setUrl);
86+
const setStatePrev = usePrevious(setState);
87+
const setStateStable = React.useRef(setState);
88+
89+
const [isError, setIsError] = React.useState(false);
90+
const isInit = setUrlPrev
91+
const isEqual = (setUrlStable.current !== setUrlPrev || setUrlPrev !== setUrl || setStateStable.current !== setState || setStatePrev !== setState)
92+
if (isInit && isEqual && !isError) {
93+
setIsError(true)
94+
}
95+
if (isError) return null;
96+
8197
return (
8298
<div className={className}>
8399
<div className="flex-1 border border-grey rounded-md p-4 shadow-md">

packages/shared/usePrevious.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react";
2+
3+
export function usePrevious<T>(value: T) {
4+
const ref = React.useRef<T>(); // Create a mutable ref
5+
6+
React.useEffect(() => {
7+
ref.current = value;
8+
}, [value]);
9+
10+
return ref.current;
11+
}

0 commit comments

Comments
 (0)