英文:
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 tests,或者通过一个 环境变量 告诉 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"
},
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论