React 版本 18中对严格模式的更改导致我的代码渲染两次,这会导致axios abort 控制器出现错误,但我不知道如何在应用程序渲染两次后从浏览器控制台清除错误。
请注意:我正在开发一个注册/登录应用程序,即使在我成功登录后,由于axios错误, React也会将我带回登录页面
useEffect(() => {
let isMounted = true;
// used by axios to cancel request
const controller = new AbortController();
const getGoals = async () => {
try {
const response = await goalPrivate.get("/goals", {
// option to cancel request
signal: controller.signal
})
console.log(response?.data);
// set goals state when component mounts
isMounted && setGoals(response?.data);
} catch (error) {
console.log(error.message);
// when refreshToken expires
navigate("/login", { state: { from: …Run Code Online (Sandbox Code Playgroud) 简而言之,如何在 React 18 中禁用严格模式?我正在使用 React 18 和 create-react-app。
React 中有没有一种方法——无论是通过代码还是通过 React 开发工具——来查看组件是否正在ReactStrictMode中渲染?在我的梦想世界中,我可以有某种常数console.log,比如布尔值React.isStrictModeOnForThisComponentRendering;或者,当您在 React 开发工具中检查某个组件时,它会在侧面板的某个位置显示它是否在 StrictMode 下渲染。
明确地说,这个问题是:
<React.StrictMode>,尽管它也可以通过某些框架中的配置来设置,例如Next.js)StrictMode,而不是 JavaScript 的( 'use strict';) 或TypeScript 的严格模式。这是一个重载的短语,但是 watcha 会怎样呢?考虑下面的片段。在 React 18 中,count每次渲染都会在控制台上打印两次,但在 React 17 中只打印一次。
反应 18 示例:
function App() {
const [count, setCount] = React.useState(0);
console.log(count);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
反应 17 示例
function App() {
const [count, setCount] = React.useState(0);
console.log(count);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);Run Code Online (Sandbox Code Playgroud)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> …Run Code Online (Sandbox Code Playgroud)我用来useRef保存 prop 的最新值,以便稍后可以在异步调用的回调(例如 onClick 处理程序)中访问它。我使用 ref 而不是放入valueuseCallback 依赖项列表,因为我预计该值会频繁更改(当使用新的组件重新渲染时value),但 onClick 处理程序很少被调用,因此它是不值得在每次值更改时为元素分配新的事件侦听器。
function MyComponent({ value }) {\n const valueRef = useRef(value);\n valueRef.current = value; // is this ok?\n\n const onClick = useCallback(() => {\n console.log("the latest value is", valueRef.current);\n }, []);\n\n ...\n}\nRun Code Online (Sandbox Code Playgroud)\nReact Strict Mode的文档让我相信执行副作用通常render()是不安全的。
\n\n由于上述方法[包括类组件
\nrender()和函数组件体]可能会被多次调用,因此\xe2\x80\x99重要的是它们不包含副作用。忽略此规则可能会导致各种问题,包括内存泄漏和无效的应用程序状态。
事实上,当我使用引用访问旧值时,我在严格模式下遇到了问题。
\n我的问题是:是否担心从渲染函数分配的“副作用” ?valueRef.current = value例如,是否存在回调会收到过时值(或来自尚未提交的“未来”渲染的值)的情况?
我能想到的一种替代方案是useEffect确保在组件渲染后更新引用,但从表面上看,这看起来没有必要。
第一次发帖提问:)
我有一个React应用程序:
// index.js
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById('root'),
);
Run Code Online (Sandbox Code Playgroud)
我有 24 个jest测试套件,到目前为止,基本上是这样的:
act(() => {
render(
<Router>
<SomeComponentIWantToTest />
</Router>
);
});
Run Code Online (Sandbox Code Playgroud)
我想到将测试包装在 中更合适StrictMode,以更接近应用程序的实际渲染方式:
act(() => {
render(
<React.StrictMode>
<Router>
<SomeComponentIWantToTest />
</Router>
</React.StrictMode>
);
});
Run Code Online (Sandbox Code Playgroud)
尝试之后,我注意到以下几点:
act. 我能够修复这些地方。欢呼!另外,快速浏览一下文档,这似乎StrictMode只是开发的事情。那么,将测试(理论上与生产中将发生的情况有关)包装起来有意义吗React.StrictMode?
我的应用程序处于严格模式下,这使得使用 useEffect() 运行变得困难。它基本上在控制台中记录了我所有的值两次,这不是我想要实现的结果。
useEffect(() => {
console.log('logs some data')
}, []);
Run Code Online (Sandbox Code Playgroud)
有没有办法让 useEffect 只显示一次数据并将 StrictMode 保留在我的应用程序组件中?
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Run Code Online (Sandbox Code Playgroud)
我确实尝试使用 useRef 方法,但我的工作人员建议我不要使用此特定方法并尝试其他可能的outwork。
解决方案:如果您需要在组件中保留严格模式,但需要使 useEffect 不渲染两次,您可以使用 useRef :
例子:
let shouldlog = useRef(true);
useEffect(() => {
if (shouldlog.current) {
shouldlog.current = false;
console.log("component mounted");
}
return () => console.log("function cleaned up");
}, []);
Run Code Online (Sandbox Code Playgroud) 我正在阅读文档并了解到 React仅StrictMode用于开发,它解释了为什么我们有双重调用。
这很好,但这是否意味着我必须StrictMode为我的生产禁用手动功能,或者反应build命令是否会自行执行此操作?
另一个 React 18 严格模式问题。我知道 React 将调用渲染和效果函数两次,以突出即将推出的功能中潜在的内存泄漏。我还不明白的是如何正确处理这个问题。我的问题是,我无法正确卸载第一个渲染结果,因为两个 useEffect 调用是使用第二个渲染的状态执行的。这是一个例子来展示我的意思。
const ref = useRef(9);
const id = useId();
console.log('@@ initial id', id);
console.log('@@ initial ref', ref.current);
ref.current = Math.random();
console.log('@@ random ref', ref.current);
useEffect(() => {
console.log('@@ effect id', id);
console.log('@@ effect ref', ref.current);
return () => {
console.log('@@ unmount id', id);
console.log('@@ unmount ref', ref.current);
};
});
Run Code Online (Sandbox Code Playgroud)
这是日志输出
@@ initial id :r0:
@@ initial ref 9
@@ random ref 0.26890444169781214
@@ initial id :r1:
@@ initial ref 9
@@ random ref …Run Code Online (Sandbox Code Playgroud) 我正在处理我的项目,我注意到当打开严格模式时,它会将两个相同的元素推入我的数组中。当严格模式关闭时,它仅将一个元素推入数组。有什么解释为什么会发生这种情况吗?
import {getRandomNumber} from './utils';
export function registerTicket() {
const newTicket = {
number: getRandomNumber(),
color: 'red',
}
this.setState((prevState) => {
prevState.tickets.push(newTicket);
return {
remainingTickets: --prevState.remainingTickets,
tickets: prevState.tickets,
}
})
}
Run Code Online (Sandbox Code Playgroud)
这是我的状态。
this.state = {
winningNumber: getRandomNumber(),
remainingTickets: 5,
tickets: [],
finished: false
};
Run Code Online (Sandbox Code Playgroud)