首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React Maximum update depth exceeded in only in test (仅在测试中由useEffect导致的React最大更新深度超出错误)

React Maximum update depth exceeded in only in test (仅在测试中由useEffect导致的React最大更新深度超出错误)
EN

Stack Overflow用户
提问于 2021-01-14 19:55:59
回答 1查看 470关注 0票数 1

我正在尝试使用jest和react-testing-library为我的react组件编写一些测试。

我的组件如下所示:

代码语言:javascript
复制
//DocumentTable.js
import {useTranslation} from "react-i18next";
import ReactTable from "react-table-6";
import {connect} from "react-redux";
...

export const DocumentTable = ({documents, getDocuments, ...}) => {
    const {t} = useTranslation();
    const [data, setData] = useState([])

    useEffect(() => {
        getDocuments();
    }, [])

    useEffect(() => {
        setData(() => translate(documents.map(doc => Object.assign({}, doc))))
    }, [documents, t])

    const translate = (tempDocuments) => {
        if (tempDocuments[0]) {
            if (tempDocuments[0].name) {
                tempDocuments.forEach(doc => doc.name = t(doc.name));
            }
            if (tempDocuments[0].documentStatus) {
                tempDocuments.forEach(doc => doc.documentStatus = t(doc.documentStatus));
            }
        }
        return tempDocuments;
    }
    ...

        return (
            <div className="col m-0 p-0 hidden-overflow-y">

                <ReactTable
                    className="bg-dark dark-table"

                    data={data}
            ...
            )
}

...

export default connect(mapStateToProps, matchDispatchToProps)(DocumentTable);

正如您所看到的,我正在使用redux和react-i18next中的翻译。我使用这个组件来显示从react-table-v6的ReactTable组件中的prop文档接收到的值。为了避免编辑我的原始值,我创建了documents数组的深层副本,翻译它并将其放入表中直接使用的数据中。

我已经开始编写我的测试,如果我可以使用react- test -library正确地呈现我的组件:

代码语言:javascript
复制
//DocumentTable.test.js
import React from 'react'
import {render} from '@testing-library/react'
import {DocumentTable} from "../../../components/content/DocumentTable";
import {I18nextProvider} from "react-i18next";
import i18n from "../../../i18n";

it("Should render component", () => {
    const documents = [
        {
            name: "favourite",
            documentStatus: "new"

        },
        {
            name: "simple",
            documentStatus: "edited"
        }
    ]

    render(
        <I18nextProvider i18n={i18n}>
            <DocumentTable documents={documents} getDocuments={jest.fn()}/>
        </I18nextProvider>
    );
})

一切似乎都很顺利。然而,我想使用useTranslation钩子的模拟,就像我在其他组件测试中所做的那样。我的模拟是:

代码语言:javascript
复制
//_mocks_/react-18next.js
module.exports = {
    useTranslation: () => ({
        t: key => key,
        i18n: {}
    }),
}

为了使用它,我在jest config中添加了属性:

代码语言:javascript
复制
//package.json
  "jest": {
    "moduleNameMapper": {
      "react-i18next": "<rootDir>/src/tests/_mocks_/react-i18next.js"
    }
  },

我简化了我的测试:

代码语言:javascript
复制
//DocumentTable.test.js
import React from 'react'
import {render} from '@testing-library/react'
import {DocumentTable} from "../../../components/content/DocumentTable";

it("Should render component", () => {
    const documents = [
        {
            name: "favourite",
            documentStatus: "new"

        },
        {
            name: "simple",
            documentStatus: "edited"
        }
    ]

    render(
          <DocumentTable documents={documents} getDocuments={jest.fn()}/>
    );
})

现在,当我运行我的测试时,我得到以下错误:

代码语言:javascript
复制
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
        in DocumentTable (at DocumentTable.test.js:89)

我不明白这是怎么回事。我得出的结论是,问题是由DocumentTable.js文件中的useEffect钩子引起的。当我不创建道具的副本,而是直接翻译它时:

代码语言:javascript
复制
useEffect(() => {
    setData(() => translate(documents))
}, [documents, t])

一切都能正常工作。但我必须继续创建它的副本(当用户更改语言时,我希望再次翻译原始文档)。我该怎么处理呢?提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-14 20:08:11

问题是,您的模拟每次都会返回一个新函数t,这将触发组件中的useEffect,因为t是一个依赖项。

使用

代码语言:javascript
复制
//_mocks_/react-18next.js
const t = key => key;
module.exports = {
    useTranslation: () => ({
        t,
        i18n: {}
    }),
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65718513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档