问题描述
这是一个演示:https://stackblitz.com/edit/react-ts-rttbjn
该演示正在按我的意愿运行。但是在PagingList.tsx
中,将引发ESLint警告:
ESLint: React Hook useEffect has a missing dependency: 'loadAfter'. Either include it or remove the dependency array.(react-hooks/exhaustive-deps)
但是无法使用[loadAfter]
。
所以我很困惑,为什么loadAfter
在重新渲染时会改变?最佳做法是什么?
PS:无法正常运行的演示,无限重新渲染:https://stackblitz.com/edit/react-ts-kl67zc
主要代码段:
PS:.eslintrc.js
:
// eslint-disable-next-line no-undef
module.exports = {
root: true,parser: "@typescript-eslint/parser",plugins: ["@typescript-eslint","jest"],extends: [
"eslint:recommended","plugin:@typescript-eslint/recommended","prettier/@typescript-eslint","plugin:react/recommended","plugin:react-hooks/recommended","plugin:jest/recommended",],settings: {
react: {
version: "16.13",},};
index.tsx
:
import React,{ FunctionComponent,useCallback } from "react";
import { PagingList } from "./PagingList";
import ReactDOM from "react-dom";
type Piece = {
id: number;
};
const MAX_COUNT = 20;
async function getAfter(
size: number,id?: number
): Promise<[Piece[],boolean]> {
const from = Math.max(0,id || 0);
const toExclusive = Math.min(from + size,MAX_COUNT);
const items = Array.from({
length: toExclusive - from,}).map((_,offset) => ({ id: from + offset + 1 }));
return new Promise((resolve) =>
setTimeout(() => resolve([items,toExclusive < MAX_COUNT]),1000)
);
}
async function getBefore(
size: number,boolean]> {
const toExclusive = Math.max(0,(id || 0) - 1);
const from = Math.max(toExclusive - size,0);
const items = Array.from({
length: toExclusive - from,from > 0]),1000)
);
}
const App: FunctionComponent = () => {
const Child = (piece: Piece) => (
<div key={piece.id}>
<span>Id: </span> {piece.id}
</div>
);
const getAfterCallback = useCallback(
(size: number,id?: number) => getAfter(size,id),[]
);
const getBeforeCallback = useCallback(
(size: number,id?: number) => getBefore(size,[]
);
return (
<PagingList
childFunction={Child}
getAfter={getAfterCallback}
getBefore={getBeforeCallback}
/>
);
};
ReactDOM.render(<App />,document.getElementById('root'));
PagingList.tsx [Workable but with error]
:
import React,{
FunctionComponent,useCallback,useEffect,useState,} from "react";
const QUERY_SIZE = 10;
type Data = { id: number };
interface Props {
childFunction: (data: Data) => JSX.Element;
getAfter: (next: number,after?: number) => Promise<[Data[],boolean]>;
getBefore: (last: number,before?: number) => Promise<[Data[],boolean]>;
}
export const PagingList: FunctionComponent<Props> = ({
childFunction,getAfter,getBefore,}) => {
const [after,setAfter] = useState<number | undefined>(undefined);
const [before,setBefore] = useState<number | undefined>(undefined);
const [data,setData] = useState<Data[]>([]);
const [hasNext,setHasNext] = useState(false);
const [hasLast,setHasLast] = useState(false);
const [isLoading,setLoading] = useState(false);
const loadAfter = useCallback(async () => {
if (isLoading) {
console.log("is loading");
return;
}
setLoading(true);
const [d,b] = await getAfter(QUERY_SIZE,after);
setHasNext(b);
setData(d);
setAfter(d[d.length - 1].id);
setBefore(d[0].id);
setHasLast(true);
setLoading(false);
},[after,isLoading]);
const loadBefore = useCallback(async () => {
if (isLoading) {
console.log("is loading");
return;
}
setLoading(true);
const [d,b] = await getBefore(QUERY_SIZE,before);
setHasLast(b);
setData(d);
setAfter(d[d.length - 1].id);
setBefore(d[0].id);
setHasLast(true);
setLoading(false);
},[before,isLoading]);
useEffect(() => {
loadAfter();
// ESLint: React Hook useEffect has a missing dependency: 'loadAfter'. Either include it or remove the dependency array.(react-hooks/exhaustive-deps)
// But `[loadAfter]` as dep array is not working
},[getAfter]);
const body = () => {
if (isLoading) {
return <div>Loading...</div>;
} else {
return (
<div>
<div>{data.map((d) => childFunction(d))}</div>
<button disabled={!hasLast} onClick={loadBefore}>
Last Page
</button>
<button disabled={!hasNext} onClick={loadAfter}>
Next Page
</button>
</div>
);
}
};
return body();
};
PagingList.tsx [Not Working but no warning]
:
import React,isLoading]);
useEffect(() => {
loadAfter();
// Now re-render infinitely,but Now eslint warning
},[loadAfter]);
const body = () => {
if (isLoading) {
return <div>Loading...</div>;
} else {
return (
<div>
<div>{data.map((d) => childFunction(d))}</div>
<button disabled={!hasLast} onClick={loadBefore}>
Last Page
</button>
<button disabled={!hasNext} onClick={loadAfter}>
Next Page
</button>
</div>
);
}
};
return body();
};
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)