使用react的useEffect编写组建报没有依赖的警告

重度胡癌患者
  • 107
import React, { FC, useEffect, useState } from 'react';
import api_tool from 'service/tool';
import { Card, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';

interface WhoisProps {
    keyword: string;
    callback?: () => void
}
interface WhoisItem {
    domain: string;
    registration_date: string;
    registration_status: string;
    registrant_country: string;
    registrant_organization: string;
    registrant_email: string;
    registrant_name: string;
    registrant_telephone: string;
    sponsoring: string;
    update_date: string;
    expiry_date: string;
    name_servers: string;
}
const Dsn: FC<WhoisProps> = ({ keyword, callback }) => {
    const [displayData, setDisplayData] = useState(undefined);
    const [searchWord, setSearchWord] = useState<string>('');
    const loadData = async () => {
        if (!keyword) {
            return;
        }
        setSearchWord(keyword);
        try {
            const { data } = await api_tool.toolWhois(keyword);
            setDisplayData(data);
            callback && callback();
        } catch (error) {
            setDisplayData([])
            setSearchWord('')
            callback && callback();
        }
    };
    const columns: ColumnsType<WhoisItem> = [
        {
            title: '序号',
            render: (text: string, record: WhoisItem,index: number) => index + 1
        },
        {
            title: '注册人',
            dataIndex: 'registrant_organization'
        },
        {
            title: '注册邮箱',
            width: 100,
            dataIndex: 'registrant_email'
        },
        {
            title: '联系电话',
            width: 100,
            dataIndex: 'registrant_telephone'
        },
        {
            title: '注册时间',
            dataIndex: '',
            render: (text: string, record: WhoisItem, index: number) => {
                return record.registration_date;
            }
        },
        {
            title: '过期时间',
            dataIndex: '',
            render: (text: string, record: WhoisItem, index: number) => {
                return record.expiry_date;
            }
        },
        {
            title: '域名服务器',
            width: 100,
            dataIndex: '',
            render: (text: string, record: WhoisItem, index: number) => {
                return record.name_servers;
            }
        },
        {
            title: '托管商',
            dataIndex: 'sponsoring'
        }
    ];

    useEffect(() => {
        loadData();
    }, [keyword]);
    return (
        <div>
            {displayData && searchWord && (
                <Card title={`${searchWord}域名查询Whois结果`}>
                    <Table
                        pagination={false}
                        scroll={{ x: 'max-content' }}
                        columns={columns}
                        rowKey={() => Math.random()}
                        dataSource={displayData || []}
                    ></Table>
                </Card>
            )}
        </div>
    );
};
export default Dsn;

请问下在reactHooks下我这么写一个组件,需要依赖keyword的变更去请求数据。
现在控制台一直报警告如下。

  Line 99:8:  React Hook useEffect has a missing dependency: 'loadData'. Either include it or remove the dependency array

有没有好的处理方案,如果是建议我关闭eslint的校验就算了。

回复
阅读 621
2 个回答

可以修改成下面这样

function usePersistFn<T extends Function>(fn: T): T {
  var fnRef = useRef<T>(fn);
  fnRef.current = fn;

  var persistFn = useRef<T>();

  if (!persistFn.current) {
    persistFn.current = (function (...args) {
      return fnRef.current.apply(this, args);
    } as unknown) as T;
  }

  return persistFn.current;
}

const Dsn: FC<WhoisProps> = ({ keyword, callback }) => {
  ...
  
  const loadData = usePersistFn(async () => {
     ...
  });

  useEffect(() => {
    loadData();
  }, [keyword, loadData]);

  ...
};
你也可以把loadData包在useCallback中并在他的deps数组中加上keywordcallback从而让警告消失,不过这种情况把对loadData的eslint关闭反而是个不错的方案,因为keyword和loadData总是同时变化的useEffect并不会因为loadData包裹在useCallback中而减少调用次数,而且useCallback中的deps数组会在每次更新时和前一轮时的deps数组进行比较,像这种没有优化效果的useCallback实际上是可以完全去掉的,不过你也可以用usePersistFn把useCallback替换了这样可以省去每次更新时deps数组的比较而且他返回的函数引用永远不变,优化效果相较于useCallback更优秀,usePersistFn的原理看这里

loadData函数声明用useCallback包裹一下,依赖写到useCallback里面,而且

if (!keyword) {
   return
}

移动到useEffect里面,也加上依赖数组就好了。

你知道吗?

宣传栏