React16源码: React中的renderRoot的错误处理的源码实现

2025年人形机器人产业研究 人形机器人是一种模仿人类外形、动作和行为的机器人,旨在替代或辅助人类完成各种任务。其显著特征包括人类外形、动作模仿和智能交互能力。根据形态和功能,人形机器人可分为小型、中型、大型以及服务型、工业型、救援型和娱乐型等类别。发展历程经历了初始阶段、高度集成系统阶段和突破性进展阶段,技术不断进步。关键技术包括执行系统、控制系统和感知与交互系统,涉及机械结构、运动控制、平衡控制、任务执行控制以及感知与交互能力。主要研究方向包括外部仿人化和内部仿生,前者关注外观设计、动作控制和任务执行能力,后者致力于模拟人类核心机制 阅读详情

renderRoot的错误处理


1 )概述

  • 在 completeWork这个方法之后, 再次回到 renderRoot 里面
  • 在 renderRoot 里面执行了 workLoop, 之后,对 workLoop 使用了try catch
  • 如果在里面有任何一个节点在更新的过程当中 throw Error 都会被catch到
  • catch到之后就是错误处理
    • 给报错节点增加 incomplete 副作用
      • incomplete 的副作用在 completeUnitOfWork 的时候,用来进行判断
      • 是要调用 completeWork,还是调用 unwindWork
    • 需要给父链上具有 error boundary 的节点增加副作用
      • 让它去收集错误以及进行一定的处理
    • 还需要创建错误相关的更新

2 )源码

定位到 packages/react-reconciler/src/ReactFiberScheduler.js#L1293

在 renderRoot 里面的 do while 循环中

do {
    try {
      workLoop(isYieldy);
    // 在catch里面得到了一个 thrownValue, 这是一个error
    } catch (thrownValue) {
      resetContextDependences();
      resetHooks();

      // Reset in case completion throws.
      // This is only used in DEV and when replaying is on.
      let mayReplay;
      if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
        mayReplay = mayReplayFailedUnitOfWork;
        mayReplayFailedUnitOfWork = true;
      }

      // 如果 nextUnitOfWork 等于 null,这是一个不属于正常流程里面的一个情况
      // 因为 nextUnitOfWork 是我们在更新一个节点之前,它是有值的更新
      // 更新节点之后,它会被赋成一个新的值
      // 一般来说它不应该是会存在 nextUnitOfWork 是 null 的一个情况
      // 即便 throw error 了,上一个 nextUnitOfWork 也没有主动去把它消除
      if (nextUnitOfWork === null) {
        // This is a fatal error.
        // 为 null 这种情况,被认为是一个致命的错误
        didFatal = true;
        // 调用 onUncaughtError,无法处理的错误被抛出了
        // 这个时候,react是会直接中断渲染染流程
        onUncaughtError(thrownValue);
      } else {
        // 非上述致命错误
        if (enableProfilerTimer && nextUnitOfWork.mode & ProfileMode) {
          // Record the time spent rendering before an error was thrown.
          // This avoids inaccurate Profiler durations in the case of a suspended render.
          stopProfilerTimerIfRunningAndRecordDelta(nextUnitOfWork, true);
        }

        if (__DEV__) {
          // Reset global debug state
          // We assume this is defined in DEV
          (resetCurrentlyProcessingQueue: any)();
        }

        if (__DEV__ && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
          if (mayReplay) {
            const failedUnitOfWork: Fiber = nextUnitOfWork;
            replayUnitOfWork(failedUnitOfWork, thrownValue, isYieldy);
          }
        }

        // TODO: we already know this isn't true in some cases.
        // At least this shows a nicer error message until we figure out the cause.
        // https://github.com/facebook/react/issues/12449#issuecomment-386727431
        invariant(
          nextUnitOfWork !== null,
          'Failed to replay rendering after an error. This ' +
            'is likely caused by a bug in React. Please file an issue ' +
            'with a reproducing case to help us find it.',
        );

        const sourceFiber: Fiber = nextUnitOfWork;
        let returnFiber = sourceFiber.return;
        
        // 如果 returnFiber 等于 null, 说明这个错误是出现在更新 RootFiber 的过程当中
        // 那么 RootFiber 它是一个非常固定的节点,就是说它没有用户代码去进行一个参与的
        // 如果这个它出现了一个错误,也是一个致命的错误,是一个react源码级的一个错误,同上一样处理
        if (returnFiber === null) {
          // This is the root. The root could capture its own errors. However,
          // we don't know if it errors before or after we pushed the host
          // context. This information is needed to avoid a stack mismatch.
          // Because we're not sure, treat this as a fatal error. We could track
          // which phase it fails in, but doesn't seem worth it. At least
          // for now.
          didFatal = true;
          onUncaughtError(thrownValue);
        } else {
          // 这里是常规处理错误
          throwException(
            root,
            returnFiber,
            sourceFiber,
            thrownValue,
            nextRenderExpirationTime,
          );
          // 立刻完成当前节点,因为出错了,子树渲染没有意义了
          nextUnitOfWork = completeUnitOfWork(sourceFiber);
          continue;
        }
      }
    }
    break;
  } while (true);
  • 进入 onUncaughtError

    function onUncaughtError(error: mixed) {
      invariant(
        nextFlushedRoot !== null,
        'Should be working on a root. This error is likely caused by a bug in ' +
          'React. Please file an issue.',
      );
      // Unschedule this root so we don't work on it again until there's
      // another update.
      // 这时候直接把 nextFlushedRoot 设置成 NoWork,剩下的任务都不再执行了
      nextFlushedRoot.expirationTime = NoWork;
      // 处理全局变量
      if (!hasUnhandledError) {
        hasUnhandledError = true;
        unhandledError = error;
      }
    }
    
  • 进入 throwException 这个是常规处理错误的处理器

    function throwException(
      root: FiberRoot,
      returnFiber: Fiber,
      sourceFiber: Fiber,
      value: mixed,
      renderExpirationTime: ExpirationTime,
    ) {
      // 增加 Incomplete 这个 SideEffect
      // 这也是在 completeUnitOfWork 当中,去判断节点,是否有 Incomplete 的来源
      // 只有在这个节点,throw了一个异常之后,它才会被赋值 SideEffect
      // The source fiber did not complete.
      sourceFiber.effectTag |= Incomplete;
      // Its effect list is no longer valid.
      // 对 firstEffect 和 lastEffect 置 null
      // 因为它已经抛出一个异常了,子节点不会再进行渲染,不会有effect的一个链
      sourceFiber.firstEffect = sourceFiber.lastEffect = null;
    
      // 这种就匹配 Promise对象,或者 thenable 对象
      // 这个其实就对应 Suspense 相关的处理,通过 throw 一个 thenable 的对象
      // 可以让这个组件变成一个挂起的状态,等到这个 Promise 被 resolve之后,再次进入一个正常的渲染周期
      // 这部分都是跟 Suspense 相关的代码,先跳过
      if (
        value !== null &&
        typeof value === 'object' &&
        typeof value.then === 'function'
      ) {
        // This is a thenable.
        const thenable: Thenable = (value: any);
    
        // Find the earliest timeout threshold of all the placeholders in the
        // ancestor path. We could avoid this traversal by storing the thresholds on
        // the stack, but we choose not to because we only hit this path if we're
        // IO-bound (i.e. if something suspends). Whereas the stack is used even in
        // the non-IO- bound case.
        let workInProgress = returnFiber;
        let earliestTimeoutMs = -1;
        let startTimeMs = -1;
        do {
          if (workInProgress.tag === SuspenseComponent) {
            const current = workInProgress.alternate;
            if (current !== null) {
              const currentState: SuspenseState | null = current.memoizedState;
              if (currentState !== null && currentState.didTimeout) {
                // Reached a boundary that already timed out. Do not search
                // any further.
                const timedOutAt = currentState.timedOutAt;
                startTimeMs = expirationTimeToMs(timedOutAt);
                // Do not search any further.
                break;
              }
            }
            let timeoutPropMs = workInProgress.pendingProps.maxDuration;
            if (typeof timeoutPropMs === 'number') {
              if (timeoutPropMs <= 0) {
                earliestTimeoutMs = 0;
              } else if (
                earliestTimeoutMs === -1 ||
                timeoutPropMs < earliestTimeoutMs
              ) {
                earliestTimeoutMs = timeoutPropMs;
              }
            }
          }
          workInProgress = workInProgress.return;
        } while (workInProgress !== null);
    
        // Schedule the nearest Suspense to re-render the timed out view.
        workInProgress = returnFiber;
        do {
          if (
            workInProgress.tag === SuspenseComponent &&
            shouldCaptureSuspense(workInProgress.alternate, workInProgress)
          ) {
            // Found the nearest boundary.
    
            // If the boundary is not in concurrent mode, we should not suspend, and
            // likewise, when the promise resolves, we should ping synchronously.
            const pingTime =
              (workInProgress.mode & ConcurrentMode) === NoEffect
                ? Sync
                : renderExpirationTime;
    
            // Attach a listener to the promise to "ping" the root and retry.
            let onResolveOrReject = retrySuspendedRoot.bind(
              null,
              root,
              workInProgress,
              sourceFiber,
              pingTime,
            );
            if (enableSchedulerTracing) {
              onResolveOrReject = Schedule_tracing_wrap(onResolveOrReject);
            }
            thenable.then(onResolveOrReject, onResolveOrReject);
    
            // If the boundary is outside of concurrent mode, we should *not*
            // suspend the commit. Pretend as if the suspended component rendered
            // null and keep rendering. In the commit phase, we'll schedule a
            // subsequent synchronous update to re-render the Suspense.
            //
            // Note: It doesn't matter whether the component that suspended was
            // inside a concurrent mode tree. If the Suspense is outside of it, we
            // should *not* suspend the commit.
            if ((workInProgress.mode & ConcurrentMode) === NoEffect) {
              workInProgress.effectTag |= CallbackEffect;
    
              // Unmount the source fiber's children
              const nextChildren = null;
              reconcileChildren(
                sourceFiber.alternate,
                sourceFiber,
                nextChildren,
                renderExpirationTime,
              );
              sourceFiber.effectTag &= ~Incomplete;
    
              if (sourceFiber.tag === ClassComponent) {
                // We're going to commit this fiber even though it didn't complete.
                // But we shouldn't call any lifecycle methods or callbacks. Remove
                // all lifecycle effect tags.
                sourceFiber.effectTag &= ~LifecycleEffectMask;
                const current = sourceFiber.alternate;
                if (current === null) {
                  // This is a new mount. Change the tag so it's not mistaken for a
                  // completed component. For example, we should not call
                  // componentWillUnmount if it is deleted.
                  sourceFiber.tag = IncompleteClassComponent;
                }
              }
    
              // Exit without suspending.
              return;
            }
    
            // Confirmed that the boundary is in a concurrent mode tree. Continue
            // with the normal suspend path.
    
            let absoluteTimeoutMs;
            if (earliestTimeoutMs === -1) {
              // If no explicit threshold is given, default to an abitrarily large
              // value. The actual size doesn't matter because the threshold for the
              // whole tree will be clamped to the expiration time.
              absoluteTimeoutMs = maxSigned31BitInt;
            } else {
              if (startTimeMs === -1) {
                // This suspend happened outside of any already timed-out
                // placeholders. We don't know exactly when the update was
                // scheduled, but we can infer an approximate start time from the
                // expiration time. First, find the earliest uncommitted expiration
                // time in the tree, including work that is suspended. Then subtract
                // the offset used to compute an async update's expiration time.
                // This will cause high priority (interactive) work to expire
                // earlier than necessary, but we can account for this by adjusting
                // for the Just Noticeable Difference.
                const earliestExpirationTime = findEarliestOutstandingPriorityLevel(
                  root,
                  renderExpirationTime,
                );
                const earliestExpirationTimeMs = expirationTimeToMs(
                  earliestExpirationTime,
                );
                startTimeMs = earliestExpirationTimeMs - LOW_PRIORITY_EXPIRATION;
              }
              absoluteTimeoutMs = startTimeMs + earliestTimeoutMs;
            }
    
            // Mark the earliest timeout in the suspended fiber's ancestor path.
            // After completing the root, we'll take the largest of all the
            // suspended fiber's timeouts and use it to compute a timeout for the
            // whole tree.
            renderDidSuspend(root, absoluteTimeoutMs, renderExpirationTime);
    
            workInProgress.effectTag |= ShouldCapture;
            workInProgress.expirationTime = renderExpirationTime;
            return;
          }
          // This boundary already captured during this render. Continue to the next
          // boundary.
          workInProgress = workInProgress.return;
        } while (workInProgress !== null);
        // No boundary was found. Fallthrough to error mode.
        value = new Error(
          'An update was suspended, but no placeholder UI was provided.',
        );
      }
    
      // We didn't find a boundary that could handle this type of exception. Start
      // over and traverse parent path again, this time treating the exception
      // as an error.
      // renderDidError 方法 就是设置全局变量 nextRenderDidError 为 true
      renderDidError();
      // 返回错误调用信息字符串
      value = createCapturedValue(value, sourceFiber);
      let workInProgress = returnFiber;
      // 根据tag匹配处理程序
      do {
        // 它其实就是往上去找它,要找到第一个可以处理错误的 class component 
        // 来进行一个错误的update的一个创建,并且让它入栈
        // 等后期在commit的时候可以进行一个调用
        // 如果都没有,那么它会到 HostRoot 上面来进行处理错误
        // 因为 HostRoot 它相当于是一个内置的错误处理的方式
        // 也会创建对应的update,然后进行一个入队列,然后后续进行一个调用的过程
        // 这就是一个 throw exception,对于错误处理的一个情况
        switch (workInProgress.tag) {
          case HostRoot: {
            const errorInfo = value;
            workInProgress.effectTag |= ShouldCapture;
            workInProgress.expirationTime = renderExpirationTime;
            // 这个 update 类似于 setState 创建的对象
            const update = createRootErrorUpdate(
              workInProgress,
              errorInfo,
              renderExpirationTime,
            );
            enqueueCapturedUpdate(workInProgress, update);
            return;
          }
    
          case ClassComponent:
            // Capture and retry
            const errorInfo = value;
            const ctor = workInProgress.type;
            const instance = workInProgress.stateNode;
            // 它要先去判断一下,它现在没有 DidCapture 这个 SideEffect
            // 并且它是有 getDerivedStateFromError 这么一个方法
            // 或者它是有 componentDidCatch 生命周期方法
            if (
              (workInProgress.effectTag & DidCapture) === NoEffect &&
              (typeof ctor.getDerivedStateFromError === 'function' ||
                (instance !== null &&
                  typeof instance.componentDidCatch === 'function' &&
                  !isAlreadyFailedLegacyErrorBoundary(instance)))
            ) {
              // 在这种情况下,我们就可以给它加上 ShouldCapture 这个 SideEffect
              // 并且呢设置它的 expirationTime 等于 renderExpirationTime
              // 因为我要去对这个组件, 在这个周期里面进行一个更新的过程
              // 然后他也要去创建一个update调用的是 createClassErrorUpdate
              workInProgress.effectTag |= ShouldCapture;
              workInProgress.expirationTime = renderExpirationTime;
              // Schedule the error boundary to re-render using updated state
              const update = createClassErrorUpdate(
                workInProgress,
                errorInfo,
                renderExpirationTime,
              );
              enqueueCapturedUpdate(workInProgress, update);
              return;
            }
            break;
          default:
            break;
        }
        workInProgress = workInProgress.return;
      } while (workInProgress !== null);
    }
    
    • 进入 renderDidError
      // packages/react-reconciler/src/ReactFiberScheduler.js
      function renderDidError() {
        nextRenderDidError = true;
      }
      
    • 进入 createCapturedValue
      // packages/react-reconciler/src/ReactCapturedValue.js
      export function createCapturedValue<T>(
        value: T,
        source: Fiber,
      ): CapturedValue<T> {
        // If the value is an error, call this function immediately after it is thrown
        // so the stack is accurate.
        return {
          value,
          source,
          stack: getStackByFiberInDevAndProd(source),
        };
      }
      
      • 进入 getStackByFiberInDevAndProd
        function describeFiber(fiber: Fiber): string {
          switch (fiber.tag) {
            case IndeterminateComponent:
            case LazyComponent:
            case FunctionComponent:
            case ClassComponent:
            case HostComponent:
            case Mode:
              const owner = fiber._debugOwner;
              const source = fiber._debugSource;
              const name = getComponentName(fiber.type);
              let ownerName = null;
              if (owner) {
                ownerName = getComponentName(owner.type);
              }
              return describeComponentFrame(name, source, ownerName);
            default:
              return '';
          }
        }
        
        // 类似于js里面的error对象,它会有一个stack的信息
        // 就是哪个文件或者哪个方法调用的时候,它出现了错误,并且附上文件对应的代码的行数之类的信息
        export function getStackByFiberInDevAndProd(workInProgress: Fiber): string {
          let info = '';
          let node = workInProgress;
          // 形成一个错误调用信息的过程
          do {
            info += describeFiber(node);
            node = node.return;
          } while (node);
          return info;
        }
        
      • 进入 createRootErrorUpdate
        function createRootErrorUpdate(
          fiber: Fiber,
          errorInfo: CapturedValue<mixed>,
          expirationTime: ExpirationTime,
        ): Update<mixed> {
          const update = createUpdate(expirationTime);
          // Unmount the root by rendering null.
          update.tag = CaptureUpdate;
          // Caution: React DevTools currently depends on this property
          // being called "element".
          update.payload = {element: null};
          const error = errorInfo.value;
          update.callback = () => {
            // 打印 error
            onUncaughtError(error);
            logError(fiber, errorInfo);
          };
          return update;
        }
        
      • 进入 enqueueCapturedUpdate
        // 没有则创建,有则克隆
        // 挂载 update
        export function enqueueCapturedUpdate<State>(
          workInProgress: Fiber,
          update: Update<State>,
        ) {
          // Captured updates go into a separate list, and only on the work-in-
          // progress queue.
          let workInProgressQueue = workInProgress.updateQueue;
          if (workInProgressQueue === null) {
            workInProgressQueue = workInProgress.updateQueue = createUpdateQueue(
              workInProgress.memoizedState,
            );
          } else {
            // TODO: I put this here rather than createWorkInProgress so that we don't
            // clone the queue unnecessarily. There's probably a better way to
            // structure this.
            workInProgressQueue = ensureWorkInProgressQueueIsAClone(
              workInProgress,
              workInProgressQueue,
            );
          }
        
          // Append the update to the end of the list.
          if (workInProgressQueue.lastCapturedUpdate === null) {
            // This is the first render phase update
            workInProgressQueue.firstCapturedUpdate = workInProgressQueue.lastCapturedUpdate = update;
          } else {
            workInProgressQueue.lastCapturedUpdate.next = update;
            workInProgressQueue.lastCapturedUpdate = update;
          }
        }
        
      • 进入 createClassErrorUpdate
        function createClassErrorUpdate(
          fiber: Fiber,
          errorInfo: CapturedValue<mixed>,
          expirationTime: ExpirationTime,
        ): Update<mixed> {
          // 创建 update
          const update = createUpdate(expirationTime);
          // 标记 tag
          update.tag = CaptureUpdate;
          const getDerivedStateFromError = fiber.type.getDerivedStateFromError;
          // 存在 getDerivedStateFromError 则作为 payload 回调处理
          if (typeof getDerivedStateFromError === 'function') {
            const error = errorInfo.value;
            update.payload = () => {
              return getDerivedStateFromError(error);
            };
          }
        
          const inst = fiber.stateNode;
          if (inst !== null && typeof inst.componentDidCatch === 'function') {
        
            // 这个有组件错误被捕获之后,它会向上去找有能够处理捕获错误信息的这个class component 来处理
            // 如果都没有,它才会到 root 上面来进行一个处理
            // 它会根据像 getDerivedStateFromError 以及 componentDidCatch 这些生命周期方法来进行一个处理
            // 如果都没有这个指定,那么这个classcomponent 是没有一个错误处理的功能的
            // 如果有就会对应的进行这些操作来进行一个调用
            update.callback = function callback() {
              if (typeof getDerivedStateFromError !== 'function') {
                // To preserve the preexisting retry behavior of error boundaries,
                // we keep track of which ones already failed during this batch.
                // This gets reset before we yield back to the browser.
                // TODO: Warn in strict mode if getDerivedStateFromError is
                // not defined.
                markLegacyErrorBoundaryAsFailed(this);
              }
              const error = errorInfo.value;
              const stack = errorInfo.stack;
              // 输出 error
              logError(fiber, errorInfo);
              // 调用catch回调钩子 传入 stack
              this.componentDidCatch(error, {
                componentStack: stack !== null ? stack : '',
              });
              if (__DEV__) {
                if (typeof getDerivedStateFromError !== 'function') {
                  // If componentDidCatch is the only error boundary method defined,
                  // then it needs to call setState to recover from errors.
                  // If no state update is scheduled then the boundary will swallow the error.
                  warningWithoutStack(
                    fiber.expirationTime === Sync,
                    '%s: Error boundaries should implement getDerivedStateFromError(). ' +
                      'In that method, return a state update to display an error message or fallback UI.',
                    getComponentName(fiber.type) || 'Unknown',
                  );
                }
              }
            };
          }
          return update;
        }
        
  • 经过以上的处理,在调用了所有 exception 之后,最后 立马调用了 completeUnitOfWork

  • 这就说明这个节点报错了,这个节点已经完成了,它不会再继续去渲染它的子节点了

  • 因为这个节点它已经出错了,再渲染它的子节点是没有任何意义

  • 所以在这里面,如果有一个节点,出错了,就会立马对它执行 completeUnitOfWork

  • 它走的就是 unwindWork 的流程了, 这个后续来看

2021 buaa 计组上机P0 logisim 3道课上考试题 每年题目都不一样,但看看往年题可以帮助查缺补漏 第一题:组合逻辑设计 4人(1个组长和3个组员)对议题进行投票表决。组长有一票否决权。如果组长一票否决,则议题被否决。如果组长正常投票(同意、反对或者弃权),则统计同意的人数和反对的人数。当同意人数大于反对人数,则议题通过,否则议题被否决。 请设计组合逻辑电路,实现这样子的一个投票表决器 同意 反对 弃权 一票否决 组长信号 00 01 10 组员信号 00 01与11 10 第2题 时序逻辑电路设计 设计一个Mealy型电路,若序列的 阅读详情

相关推荐

Globus数据下载全攻略:从零配置到批量下载大文件(附常见问题解决)

本文详细介绍了Globus数据下载的全流程,从零配置到批量下载大文件的实用技巧,包括环境准备、高级传输策略、性能优化及常见问题解决方案。Globus作为科研数据的高效传输工具,通过并行流传输和自动校验技术,显著提升大规模数据传输的效率和可靠性。

u9v0w的博客 663

React中遇到的渲染死循环问题

刚开始学react没多久,现在边干活边学习,今天遇到了一个bug,百度了一下解决了,总结一下   当我写下面这段代码的时候,遇到了这个bug,f12之后发现,无限报警告 代码:&lt;a href = "#" onClick={this.handleShow(true)}&gt;显示&lt;/a&gt; 警告: .Warning: setState(...): Cannot update ...

qq_39674542的博客 7923

风力发电机缺陷检测平台

风力发电机缺陷检测平台相关内容展示

weixin_39779415的博客 1111

解决React卸载组件发生的问题(root.unmount())

Warning: You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.

zyq的博客 1852

GPS从入门到放弃(一) --- GPS基础原理

GPS从入门到放弃(一) — GPS基础原理 GPS,全称Global Positioning System,已经广泛应用于我们的日常生活中了,现在的智能手机 里都会自带GPS定位功能。这是一个美国的全球定位系统,虽然我们现在也有北斗了,但毕竟GPS搞的早,所以先从它开始研究起。 整个GPS系统分三大部分: 地面站 卫星 接收机 地面站负责监控。它们通过接收、测量各个卫星信号,计算卫星的运行轨...

tyst08的专栏 2万+

[ADS]单端电感和差分电感的感值和Q值计算公式

单端电感和差分电感的感值和Q值计算公式

乾巽的博客 1万+

React 16.12.0 源码解读(四)之提交任务

React提交任务部分的源码梳理和解读。

Babyfaceqian的博客 384

树莓派4B+红外传感器:手把手教你DIY一个能走黑线的智能小车(Python代码全解析)

本文详细介绍了如何使用树莓派4B和红外传感器DIY一个智能循迹小车,包括硬件配置、GPIO连接、Python代码实现及优化算法。通过动态PWM调速、状态机设计和赛道记忆算法,提升小车的循迹性能和稳定性。适合初学者和电子爱好者动手实践。

weixin_29188043的博客 270

React之setState调用unmount组件报警告

最近公司比较忙,所以更新进度比较慢,一是因为要梳理以前的代码,二是因为赶进度!!! 这个问题也是机缘巧合碰到了,正赶上这周公司网络无缘无故抽风(很慢),然后那天在调试代码的时候忽然发现浏览器报了一个这样的Warning: warn.png   其实从字面上也大概可以了解个大概,是由于setState只能更新挂载完成的组件或者正在挂载的组件,那么定位这个BUG的第一步当然是先了解组件的生命...

hahahhahahahha123456的博客 972

HP SPP download

是一个全面的系统软件和固件更新解决方案,以单个ISO映像的形式提供。该解决方案使用智能更新管理器(SUM)作为部署工具。

极致,细节 9863

FPGA实现串口升级及MultiBoot(九)BPI FLASH相关实例演示

与SPI相关知识并没有什么太多区别(别杠硬件或者架构上),相关知识点都在上面指出,大家有什么其他需要注意点,欢迎留言讨论。关于“四样错误”就不演示了,没什么太大区别,下一讲我们开始串口升级。PS:为了扩展ICAPE2原语的使用,在原来的基础上增加了几个常用FPGA ID,并在触发启动时候增加了可选电平触发或上升/下降沿触发(例化IP时选择),新版本号V1.1。

OpenFPGA的博客 1447

解决X6项目中React节点重绘时的同步卸载警告问题:终极指南

X6是一个强大的JavaScript绘图库,使用SVG和HTML进行渲染,广泛应用于流程图、拓扑图等可视化场景。在使用X6与React集成的过程中,开发者经常会遇到React节点重绘时出现的同步卸载警告问题,这可能会影响应用的性能和稳定性。 ## 🔍 问题现象与原因分析 当X6中的React节点进行重绘操作时,经常会看到类似这样的警告:"Cannot update during an exi

gitblog_01191的博客 360

YOLOv11改进策略【卷积层】| ICCV-2023 引入Dynamic Snake Convolution动态蛇形卷积,改进C3k2

基于拓扑几何约束的动态蛇卷积用于管状结构分割DSConv(Dynamic Snake Convolution,动态蛇形卷积)模块的设计主要是为了更好地处理管状结构的分割任务,解决传统卷积在处理细管状结构时的不足。

Limiiiing的博客 1629

React16源码: React中的renderRoot的源码实现

renderRoot 是一个非常复杂的方法, 它调用 workLoop 进行循环单元更新, 并且捕获错误并进行处理,最后,在走完流程之后要进行善后

Wang的专栏 1397

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

React16源码: React中的unwindWork的源码实现

在 renderRoot 的 throw Exception 里面, 对于被捕获到错误的组件进行了一些处理 并且向上去寻找能够处理这些异常的组件,比如说 class component 里面具有 getDerivedStateFromError 或者 componentDidCatch 这样的生命周期方法 这个class component 就代表它可以处理它的子树当中渲染出来的任何的错误

Wang的专栏 1768

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Warning: Can‘t perform a React state update on an unmounted component.React内存泄漏报错解决

在React开发中切换组件或者退出登录时偶尔会遇到控制台如下报错,不会有大影响仅控制台报红 原因: 报错直译:我们不能在组件销毁后设置state,防止出现内存泄漏的情况 关于react中切换路由时报以上错误,实际的原因是因为在组件挂载(mounted)之后进行了异步操作,如ajax请求或者设置了定时器等,而你在callback中进行了setState操作。当你切换路由时,组件已经被卸载(unmounted)了,此时异步操作中callback还在执行,因此setState没有得到值。 解决方案: // 适

h33413398的博客 966

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

React开发中常见问题和 Warning

React内存泄露 译文:索引。警告:无法对未挂载的组件执行React状态更新。这是一个no-op,但它表明您的应用程序中存在内存泄漏。要修复此问题,请取消componentWillUnmount方法中的所有订阅和异步任务。 解决方案, componentWillUpdate(){ this.setState = () => { ...

技术分享 1582

React Work Loop 原理

背景 - 前端体验优化 为了让 React 在检测到数据变化需要重新渲染界面的时候不会阻塞浏览器主线程,从而让用户交互体验更流畅,React 团队提出了 Work Loop 的概念,将任务拆分成小的模块,在每一个任务完成后都检测是否当前有优先级更高的任务(例如:用户与浏览器的交互),有则优先执行优先级更高的任务,没有则继续执行下一个任务。 (声明:本文所解析的所有逻辑都是为了大家能更好的通...

GuoZebin的博客 997

报错Warning: ReactDOM.render is no longer supported in React 18.Use createRoot instead.Until you...

报错Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17.

super码力的博客 3983

React Fiber 架构原理之2 —— 自底向上盘一盘 Scheduler

其中优先级定义会作为变量导出,而过期时间为内部计算任务派发顺序的参考。调度能力分为四层实现:对接浏览器的 SchedulerHostConfig、实现核心任务管理的 Scheduler、抹平接口的 SchedulerWithReactIntegration、应用 Scheduler 的 ReactFiberScheduler。

军火库 1013

react异步渲染组件_在预期异步渲染中重新使用React的组件生命周期

react异步渲染组件by Alex Brown 通过亚历克斯布朗 在预期异步渲染时重新使用React的组件生命周期挂钩 (Revisiting use of React’s Component Life Cycle Hooks in Anticipation of Async Rendering) If you’ve browsed the documentation, or kept an...

744

react内存泄漏警告

在运行react项目的时候有时会报一个红色的warning,如下图 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmou

蓝枫秋千的踩坑记录 2083

「React源码分析」七. React DOM之Root根节点操作分析

2021SC@SDUSC

u012922190的博客 1393

React开发中常见报错之组件更新错误

在React开发中,这样的报错会经常遇到:Warning: Can't perform a React state update on an unmounted component.

coder__wang的博客 1249

Fix signatures do not match the previously installed version

报错信息FAILURE: Build failed with an exception.* What went wrong: Execution failed for task ':app:installDebug'. > com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Fai

Wang的专栏 2万+

在react中 实现 base64的图片转换成formdata格式并实现上传功能

如果不想要服务端实现处理base64格式的图片的转换,那么在浏览器端来实现,部分属于伪代码,仅作为开发参考,请勿直接拷贝使用

Wang的专栏 8836
上一篇: React16源码: React中的completeWork对HostText处理含更新的源码实现
下一篇: React16源码: React中的unwindWork的源码实现
Wang's Blog
博客等级 码龄12年 7438粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值