英文:
Error: act(...) is not supported in production builds of React
问题
我在这里有一个特定的情况,我在我的React Redux应用程序中从React Testing Library中引入库,并将这些库的导入语句作为初始状态渲染到代码编辑器中:
import produce from "immer";
import { ActionType } from "../action-types";
import { Action } from "../actions";
import { Cell } from "../cell";
interface CellsState {
loading: boolean;
error: string | null;
order: string[];
data: {
[key: string]: Cell;
};
}
const initialState: CellsState = {
loading: false,
error: null,
order: [],
data: {},
};
const initialCodeSnippets = [
`import React, { useState } from 'react';
import { render, screen } from '@testing-library/react';
import user from '@testing-library/user-event';
const Counter = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount((c) => c + 1)}>Count: {count}</button>
};
render(<Counter />);`,
`console.log(a);`,
// Add more initial snippets as needed
];
const reducer = produce((state: CellsState = initialState, action: Action) => {
switch (action.type) {
case ActionType.UPDATE_CELL:
const { id, content } = action.payload;
state.data[id].content = content;
return state;
case ActionType.DELETE_CELL:
delete state.data[action.payload];
state.order = state.order.filter((id) => id !== action.payload);
return state;
case ActionType.MOVE_CELL:
const { direction } = action.payload;
const index = state.order.findIndex((id) => id === action.payload.id);
const targetIndex = direction === "up" ? index - 1 : index + 1;
if (targetIndex < 0 || targetIndex > state.order.length - 1) {
return state;
}
state.order[index] = state.order[targetIndex];
state.order[targetIndex] = action.payload.id;
return state;
case ActionType.INSERT_CELL_AFTER:
const cell: Cell = {
content: initialCodeSnippets[action.payload.orderIndex],
type: action.payload.type,
id: randomId(),
orderIndex: action.payload.orderIndex,
};
state.data[cell.id] = cell;
const foundIndex = state.order.findIndex(
(id) => id === action.payload.id
);
if (foundIndex < 0) {
state.order.unshift(cell.id);
} else {
state.order.splice(foundIndex + 1, 0, cell.id);
}
return state;
default:
return state;
}
}, initialState);
const randomId = () => {
return Math.random().toString(36).substring(2, 5);
};
export default reducer;
然而,当我这样做时,在预览窗口中出现运行时错误:
Error: act(...) is not supported in production builds of React
我不确定如何解决这个问题,因为RTL不是应用程序本身的依赖项,而是实际上被引入的。ESBuild无法找到查找RTL或任何其他库的路径,我正在为ESBuild做这个操作,因为打包工具需要它。
我将URL直接提供给ESBuild,以尝试找到特定库的源代码。
我需要在ESBuild插件中以不同的方式定义define
吗?
let service: esbuild.Service;
const bundle = async (rawCode: string) => {
if (!service) {
service = await esbuild.startService({
worker: true,
wasmURL: "https://unpkg.com/esbuild-wasm@0.8.27/esbuild.wasm",
});
}
try {
const result = await service.build({
entryPoints: ["index.js"],
bundle: true,
write: false,
plugins: [unpkgPathPlugin(), fetchPlugin(rawCode)],
define: {
"process.env.NODE_ENV": '"production"',
global: "window",
},
});
return {
code: result.outputFiles[0].text,
error: "",
};
} catch (error) {
if (error instanceof Error) {
return {
code: "",
error: error.message,
};
} else {
throw error;
}
}
};
export default bundle;
我尝试通过以下方式安装包:
npm install @testing-library/jest-dom @testing-library/react @testing-library/user-event --force
但是我在预览窗口中仍然看到运行时错误。
问题在于,在底层调用render
时,react-testing-library的作者将该函数包装在act
中,以使测试运行尽可能接近在浏览器中运行的方式。这就是为什么我会得到这个错误。由于您没有在测试环境中运行该代码,因此不支持act
。
我是否可以编写自己的render()
函数,并使用它来替代,但只是让它看起来像是在使用RTL的render
函数?
英文:
I have a specific case here where in my React Redux app I am pulling in libraries from React Testing Library and rendering the import statements of those libraries into a code editor as initial state:
import produce from "immer";
import { ActionType } from "../action-types";
import { Action } from "../actions";
import { Cell } from "../cell";
interface CellsState {
loading: boolean;
error: string | null;
order: string[];
data: {
[key: string]: Cell;
};
}
const initialState: CellsState = {
loading: false,
error: null,
order: [],
data: {},
};
const initialCodeSnippets = [
`import React, { useState } from 'react';
import { render, screen } from '@testing-library/react';
import user from '@testing-library/user-event';
const Counter = () => {
const [count, setCount] = useState(0);
return <button onClick={() => setCount((c) => c + 1)}>Count: {count}</button>
};
render(<Counter />);`,
`console.log(a);`,
// Add more initial snippets as needed
];
const reducer = produce((state: CellsState = initialState, action: Action) => {
switch (action.type) {
case ActionType.UPDATE_CELL:
const { id, content } = action.payload;
state.data[id].content = content;
return state;
case ActionType.DELETE_CELL:
delete state.data[action.payload];
state.order = state.order.filter((id) => id !== action.payload);
return state;
case ActionType.MOVE_CELL:
const { direction } = action.payload;
const index = state.order.findIndex((id) => id === action.payload.id);
const targetIndex = direction === "up" ? index - 1 : index + 1;
if (targetIndex < 0 || targetIndex > state.order.length - 1) {
return state;
}
state.order[index] = state.order[targetIndex];
state.order[targetIndex] = action.payload.id;
return state;
case ActionType.INSERT_CELL_AFTER:
const cell: Cell = {
content: initialCodeSnippets[action.payload.orderIndex],
type: action.payload.type,
id: randomId(),
orderIndex: action.payload.orderIndex,
};
state.data[cell.id] = cell;
const foundIndex = state.order.findIndex(
(id) => id === action.payload.id
);
if (foundIndex < 0) {
state.order.unshift(cell.id);
} else {
state.order.splice(foundIndex + 1, 0, cell.id);
}
return state;
default:
return state;
}
}, initialState);
const randomId = () => {
return Math.random().toString(36).substring(2, 5);
};
export default reducer;
However, when I do so, in the preview window I get a runtime error saying that:
> Error: act(...) is not supported in production builds of React
I am not sure how to resolve this, since RTL is not a dependency in the application itself but actually being pulled in. ESBuild is not figuring out what path to look at to find RTL or any other library, I am doing it for ESBuild because the bundler needs it.
I take the URL and provide it directly to ESBuild to try to find the source code for a particular library.
Do I need to define define
differently in the ESBuild plugin?
let service: esbuild.Service;
const bundle = async (rawCode: string) => {
if (!service) {
service = await esbuild.startService({
worker: true,
wasmURL: "https://unpkg.com/esbuild-wasm@0.8.27/esbuild.wasm",
});
}
try {
const result = await service.build({
entryPoints: ["index.js"],
bundle: true,
write: false,
plugins: [unpkgPathPlugin(), fetchPlugin(rawCode)],
define: {
"process.env.NODE_ENV": '"production"',
global: "window",
},
});
return {
code: result.outputFiles[0].text,
error: "",
};
} catch (error) {
if (error instanceof Error) {
return {
code: "",
error: error.message,
};
} else {
throw error;
}
}
};
export default bundle;
I tried installing the packages via:
npm install @testing-library/jest-dom @testing-library/react @testing-library/user-event --force
But I still see that runtime error in the preview window.
So the problem is that under the hood, when I'm calling render, the authors of react-testing-library are wrapping that function in act to make the test run as similar to how it runs in the browser as it can. That's why I am getting this error. Since you're not running that code inside a test environment, act is not supported.
Could I maybe write my own render()
function and using it instead, but only making it seem like it's using the render
function from RTL?
答案1
得分: 0
你要翻译的内容如下:
你要么使用生产版本的应用程序来运行你的 jest 测试,要么通过 环境变量 告诉 jest 将其视为生产环境。
在运行 jest
之前,请确保设置 NODE_ENV=test
,或者一直设置为 NODE_ENV=development
。
这个关于一个非常类似问题的 Github 问题可能会有帮助 (https://github.com/vercel/next.js/discussions/35676)。
示例 package.json
文件:
{
...
"scripts": {
"test": "NODE_ENV=test jest"
},
...
}
英文:
You are either running your jest tests with the production build of your application or telling jest to treat it as if it were production with an environment variable.
Make sure to set NODE_ENV=test
before running jest
or set NODE_ENV=development
all the way.
This issue on Github about a very similar problem might be helpful (https://github.com/vercel/next.js/discussions/35676).
sample package.json
file:
{
...
"scripts": {
"test": "NODE_ENV=test jest"
},
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论