React 不呈现正确的条件元素
React does not render correct conditional element
我正在使用最新版本的 React 和最新的状态 mobx。
我试图让错误(或任何消息)出现一次,然后在操作时消失。
仅使用状态我没有想到简单的方法来做到这一点所以我“发明”的是以下内容:
在 mobx 状态下,我会保留是否有错误、错误及其描述。
在简单的 JS 对象(对更改没有反应)中,我保留是否显示此错误。
因此,当第一次显示错误时,布局呈现 - 它保存在显示错误的简单 JS 对象中,如果第二次显示错误 - 将其从 mobx 中删除(从而更新 UI)。这是我对一次性消息使用反应性和非反应性状态的解决方法。
然而,我在尝试实施时遇到了以下行为:
console.log('Render MainLayout...');
if (state.hasError || state.hasSuccess) {
console.log('Has message');
if (NonReactiveState.messageDisplayed) {
console.log('Message already displayed - hiding');
state.clearMessages();
} else {
console.log('Displaying message...');
NonReactiveState.messageDisplayed = true;
}
}
if (state.hasError) {
console.log('Displaying error...');
dummy = <div className="dummy-element-error"></div>
errorAlert = (
<Alert variant="danger">
<Alert.Heading>{state.errorTitle}</Alert.Heading>
<p>{state.errorDescription}</p>
</Alert>
)
} else {
console.log('No error to display');
dummy = <div className="dummy-element-no-error"></div>
}
if (state.hasSuccess) {
console.log('Displaying success...');
successAlert = (
<Alert variant="success">
<Alert.Heading>{state.successTitle}</Alert.Heading>
<p>{state.successDescription}</p>
</Alert>
)
}
console.log('error el', errorAlert);
console.log('success el', successAlert);
console.log(state);
在控制台中呈现错误后,我有以下内容:
jsx 看起来像这样:
...
<div className="content">
<div className="container-fluid">
<div className="invalid-class-bla">
{dummy}
{errorAlert}
{successAlert}
</div>
...
</div>
</div>
...
但是我想不通为什么我的 HTML 不显示警报而是显示以下内容:
它确实有来自正确 IF 块的控制台日志。它确实表明 errorAlert 不为空。但最后 HTML 错误警报是空的,并且 'debug' 元素包含无错误 class.
我可能遗漏了一些真正转储在这里的东西,但我一直坚持下去。
归根结底 - 我对一次性消息使用非反应状态的“天才”想法将不适用于 React。经过大量调试后我发现 React 出于各种原因秘密地重新渲染组件,隐藏所有 console.log 和其他输出。
我设置了一个静态渲染计数器,每次调用该函数时它都会递增 1。我在功能组件的开头生成一次该数字,并在 console.log 和组件 JSX 中打印该数字。
计数器看起来像这样:
let id = 0;
const uniqueId = () => {
return 'id-' + id++;
};
export default uniqueId;
简单组件:
const Debug = () => {
const id = uniqueId();
console.log('Render id: ' + id);
return (
<div className="render-id">
{id}
</div>
);
};
export default Debug;
结果是组件中的console.log总是1-2渲染落后于渲染的JSX的实际内容。这意味着在我看到 console.log 打印的初始渲染后,组件在后台渲染并禁用输出。
这实际上意味着它多次执行 'one-time' 逻辑,这打破了我基于真实渲染计数的非反应状态的整个想法。
我想我必须考虑另一种基于反应状态的单次消息渲染的想法,以便 React 可以在隐藏的重新渲染期间在内部管理它。
编辑
好的,经过更多的调试,我发现我的问题来自React在开发模式下的严格模式。文档明确指出:
Strict mode can’t automatically detect side effects for you, but it
can help you spot them by making them a little more deterministic.
This is done by intentionally double-invoking the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer
在没有严格模式的情况下,功能会按预期工作...
编辑 2
我最初关于非反应状态不起作用的说法是错误的。它正在工作,但对它的任何更改都必须在 useEffect
挂钩中发生,因此它不会在严格模式双重执行期间执行。所以我的错误是我试图直接在功能组件的主体中进行更改(副作用)。这相当于 class 组件中的 render() 函数。这是不正确的。
对任何事物的任何改变,不管它是否是反应性的,都必须在 useEffect
钩子中发生,否则结果是不可预测的和随机的。基本错误但违反了基本原则。
我正在使用最新版本的 React 和最新的状态 mobx。
我试图让错误(或任何消息)出现一次,然后在操作时消失。 仅使用状态我没有想到简单的方法来做到这一点所以我“发明”的是以下内容:
在 mobx 状态下,我会保留是否有错误、错误及其描述。 在简单的 JS 对象(对更改没有反应)中,我保留是否显示此错误。 因此,当第一次显示错误时,布局呈现 - 它保存在显示错误的简单 JS 对象中,如果第二次显示错误 - 将其从 mobx 中删除(从而更新 UI)。这是我对一次性消息使用反应性和非反应性状态的解决方法。
然而,我在尝试实施时遇到了以下行为:
console.log('Render MainLayout...');
if (state.hasError || state.hasSuccess) {
console.log('Has message');
if (NonReactiveState.messageDisplayed) {
console.log('Message already displayed - hiding');
state.clearMessages();
} else {
console.log('Displaying message...');
NonReactiveState.messageDisplayed = true;
}
}
if (state.hasError) {
console.log('Displaying error...');
dummy = <div className="dummy-element-error"></div>
errorAlert = (
<Alert variant="danger">
<Alert.Heading>{state.errorTitle}</Alert.Heading>
<p>{state.errorDescription}</p>
</Alert>
)
} else {
console.log('No error to display');
dummy = <div className="dummy-element-no-error"></div>
}
if (state.hasSuccess) {
console.log('Displaying success...');
successAlert = (
<Alert variant="success">
<Alert.Heading>{state.successTitle}</Alert.Heading>
<p>{state.successDescription}</p>
</Alert>
)
}
console.log('error el', errorAlert);
console.log('success el', successAlert);
console.log(state);
在控制台中呈现错误后,我有以下内容:
jsx 看起来像这样:
...
<div className="content">
<div className="container-fluid">
<div className="invalid-class-bla">
{dummy}
{errorAlert}
{successAlert}
</div>
...
</div>
</div>
...
但是我想不通为什么我的 HTML 不显示警报而是显示以下内容:
它确实有来自正确 IF 块的控制台日志。它确实表明 errorAlert 不为空。但最后 HTML 错误警报是空的,并且 'debug' 元素包含无错误 class.
我可能遗漏了一些真正转储在这里的东西,但我一直坚持下去。
归根结底 - 我对一次性消息使用非反应状态的“天才”想法将不适用于 React。经过大量调试后我发现 React 出于各种原因秘密地重新渲染组件,隐藏所有 console.log 和其他输出。
我设置了一个静态渲染计数器,每次调用该函数时它都会递增 1。我在功能组件的开头生成一次该数字,并在 console.log 和组件 JSX 中打印该数字。
计数器看起来像这样:
let id = 0;
const uniqueId = () => {
return 'id-' + id++;
};
export default uniqueId;
简单组件:
const Debug = () => {
const id = uniqueId();
console.log('Render id: ' + id);
return (
<div className="render-id">
{id}
</div>
);
};
export default Debug;
结果是组件中的console.log总是1-2渲染落后于渲染的JSX的实际内容。这意味着在我看到 console.log 打印的初始渲染后,组件在后台渲染并禁用输出。
这实际上意味着它多次执行 'one-time' 逻辑,这打破了我基于真实渲染计数的非反应状态的整个想法。
我想我必须考虑另一种基于反应状态的单次消息渲染的想法,以便 React 可以在隐藏的重新渲染期间在内部管理它。
编辑
好的,经过更多的调试,我发现我的问题来自React在开发模式下的严格模式。文档明确指出:
Strict mode can’t automatically detect side effects for you, but it can help you spot them by making them a little more deterministic. This is done by intentionally double-invoking the following functions:
- Class component constructor, render, and shouldComponentUpdate methods
- Class component static getDerivedStateFromProps method
- Function component bodies
- State updater functions (the first argument to setState)
- Functions passed to useState, useMemo, or useReducer
在没有严格模式的情况下,功能会按预期工作...
编辑 2
我最初关于非反应状态不起作用的说法是错误的。它正在工作,但对它的任何更改都必须在 useEffect
挂钩中发生,因此它不会在严格模式双重执行期间执行。所以我的错误是我试图直接在功能组件的主体中进行更改(副作用)。这相当于 class 组件中的 render() 函数。这是不正确的。
对任何事物的任何改变,不管它是否是反应性的,都必须在 useEffect
钩子中发生,否则结果是不可预测的和随机的。基本错误但违反了基本原则。