繁体   English   中英

React 没有呈现正确的条件元素

[英]React does not render correct conditional element

我正在使用最新版本的 react with latest mobx for state。

我试图让错误(或任何消息)出现一次,然后在操作时消失。 仅使用 state 我没有想到简单的方法来做到这一点,所以我“发明”的内容如下:

在 mobx state 中,我会保留是否有错误、错误及其描述。 在简单的 JS object(对更改没有反应)中,我会保留是否显示此错误。 因此,当第一次显示错误时,布局呈现 - 它保存在显示错误的简单 JS object 中,如果显示错误,则第二次 - 从 mobx 中删除它(从而更新 UI)。 这是我使用响应式和非响应式 state 一次性消息的解决方法。

然而,试图实现我遇到了以下行为:

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 不显示警报,而是显示以下内容:

html

它确实有来自正确 IF 块的控制台日志。 它确实表明 errorAlert 不为空。 但最后在 HTML 错误警报是空的,并且“调试”元素包含无错误 class。

我可能在这里遗漏了一些真正转储的东西,但我坚持这一点。

归根结底——我的“天才”想法使用非反应性 state 来处理一次性消息不适用于 React。 经过大量调试后我发现,React 出于各种原因秘密地重新渲染组件,隐藏了所有 console.log 和其他输出。

我设置了一个 static 渲染计数器,每次调用 function 时它都会递增 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 总是在渲染的 JSX 的实际内容后面 1-2 次渲染。 这意味着该组件是在后台渲染的,在我看到 console.log 打印的初始渲染之后禁用了 output。

控制台计数器 jsx计数器

这实际上意味着它多次执行“一次性”逻辑,这打破了我基于真实渲染计数的非反应式 state 的整个想法。

我想我必须考虑基于反应式 state 的单次消息渲染的另一个想法,以便 React 可以在隐藏重新渲染期间在内部管理它。

编辑

好的,经过更多调试后,我发现我的问题来自 React 在开发模式下的严格模式。 文件明确指出:

严格模式不能自动为您检测副作用,但它可以通过使它们更具确定性来帮助您发现它们。 这是通过有意双重调用以下函数来完成的:

  • Class 组件构造函数、渲染和 shouldComponentUpdate 方法
  • Class 组件 static getDerivedStateFromProps 方法
  • Function 组件体
  • State 更新函数(setState 的第一个参数)
  • 传递给 useState、useMemo 或 useReducer 的函数

如果没有严格模式,功能将按预期工作......

编辑 2

我最初的陈述是错误的,即非反应性 state 不起作用。 它正在工作,但是对它的任何更改都必须在useEffect挂钩中发生,因此它不会在严格模式双重执行期间执行。 所以我的错误是我试图直接在功能组件的主体中进行更改(副作用)。 这等于 class 组件中的 render() function。 这是不正确的。

对任何事物的任何更改,无论它是否是反应性的,都必须在useEffect挂钩中发生,否则结果是不可预测的和随机的。 基本错误,但违反了基本原则。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM