微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决React 没有呈现正确的条件元素

我正在使用最新版本的 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);

在控制台中呈现错误后,我有以下内容

console

jsx 看起来像这样:

...
<div className="content">
    <div className="container-fluid">
        <div className="invalid-class-bla">
            {dummy}
            {errorAlert}
            {successAlert}
        </div>
        ...
    </div>
</div>
...

但是我无法理解为什么我的 HTML 不显示警报而是具有以下内容

html

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

我可能会遗漏一些真正在这里转储的东西,但我一直坚持下去。

解决方法

归根结底 - 我对一次性消息使用非反应状态的“天才”想法不适用于 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总是在JSX实际渲染内容后面1-2次渲染。这意味着组件在后台渲染,在我看到 console.log 打印的初始渲染后禁用输出。

console counter jsx counter

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

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

编辑

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

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

  • 类组件构造函数、render 和 shouldComponentUpdate 方法
  • 类组件静态 getDerivedStateFromProps 方法
  • 函数组件主体
  • 状态更新器函数(setState 的第一个参数)
  • 传递给 useState、useMemo 或 useReducer 的函数

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

编辑 2

我最初关于非反应状态不起作用的声明是错误的。它正在工作,但对它的任何更改都必须在 useEffect 挂钩中发生,因此它不会在严格模式双重执行期间执行。所以我的错误是我试图直接在功能组件的主体中进行更改(副作用)。这相当于类组件中的 render() 函数。这是不正确的。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。