@samitouri / QOS-React / commits / 7fd1661f80

Don't warn if an unmounted component is pinged (#14158)

Don't warn if an unmounted component is pinged (#14158) * Add failing test for ping on unmounted component We had a test for this, but not outside of concurrent mode :) * Don't warn if an unmounted component is pinged

Andrew Clark committed Nov 8, 2018 at 17:24 UTC 7fd1661f80868c6006388647bd0104f5f4f3f320
2 files changed +88 -43
packages/react-reconciler/src/ReactFiberScheduler.js
+40 -43
@@ -1747,6 +1747,46 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
1747 }
1748 }
1749
1750 + if (enableSchedulerTracing) {
1751 + if (root !== null) {
1752 + const interactions = __interactionsRef.current;
1753 + if (interactions.size > 0) {
1754 + const pendingInteractionMap = root.pendingInteractionMap;
1755 + const pendingInteractions = pendingInteractionMap.get(expirationTime);
1756 + if (pendingInteractions != null) {
1757 + interactions.forEach(interaction => {
1758 + if (!pendingInteractions.has(interaction)) {
1759 + // Update the pending async work count for previously unscheduled interaction.
1760 + interaction.__count++;
1761 + }
1762 +
1763 + pendingInteractions.add(interaction);
1764 + });
1765 + } else {
1766 + pendingInteractionMap.set(expirationTime, new Set(interactions));
1767 +
1768 + // Update the pending async work count for the current interactions.
1769 + interactions.forEach(interaction => {
1770 + interaction.__count++;
1771 + });
1772 + }
1773 +
1774 + const subscriber = __subscriberRef.current;
1775 + if (subscriber !== null) {
1776 + const threadID = computeThreadID(
1777 + expirationTime,
1778 + root.interactionThreadID,
1779 + );
1780 + subscriber.onWorkScheduled(interactions, threadID);
1781 + }
1782 + }
1783 + }
1784 + }
1785 + return root;
1786 +}
1787 +
1788 +function scheduleWork(fiber: Fiber, expirationTime: ExpirationTime) {
1789 + const root = scheduleWorkToRoot(fiber, expirationTime);
1790 if (root === null) {
1791 if (__DEV__) {
1792 switch (fiber.tag) {
@@ -1761,49 +1801,6 @@ function scheduleWorkToRoot(fiber: Fiber, expirationTime): FiberRoot | null {
1801 break;
1802 }
1803 }
1764 - return null;
1765 - }
1766 -
1767 - if (enableSchedulerTracing) {
1768 - const interactions = __interactionsRef.current;
1769 - if (interactions.size > 0) {
1770 - const pendingInteractionMap = root.pendingInteractionMap;
1771 - const pendingInteractions = pendingInteractionMap.get(expirationTime);
1772 - if (pendingInteractions != null) {
1773 - interactions.forEach(interaction => {
1774 - if (!pendingInteractions.has(interaction)) {
1775 - // Update the pending async work count for previously unscheduled interaction.
1776 - interaction.__count++;
1777 - }
1778 -
1779 - pendingInteractions.add(interaction);
1780 - });
1781 - } else {
1782 - pendingInteractionMap.set(expirationTime, new Set(interactions));
1783 -
1784 - // Update the pending async work count for the current interactions.
1785 - interactions.forEach(interaction => {
1786 - interaction.__count++;
1787 - });
1788 - }
1789 -
1790 - const subscriber = __subscriberRef.current;
1791 - if (subscriber !== null) {
1792 - const threadID = computeThreadID(
1793 - expirationTime,
1794 - root.interactionThreadID,
1795 - );
1796 - subscriber.onWorkScheduled(interactions, threadID);
1797 - }
1798 - }
1799 - }
1800 -
1801 - return root;
1802 -}
1803 -
1804 -function scheduleWork(fiber: Fiber, expirationTime: ExpirationTime) {
1805 - const root = scheduleWorkToRoot(fiber, expirationTime);
1806 - if (root === null) {
1804 return;
1805 }
1806
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+48
@@ -838,5 +838,53 @@ describe('ReactSuspense', () => {
838 ]);
839 expect(root).toMatchRenderedOutput('Tab: 2 + sibling');
840 });
841 +
842 + it('does not warn if an mounted component is pinged', () => {
843 + const {useState} = React;
844 +
845 + const root = ReactTestRenderer.create(null);
846 +
847 + let setStep;
848 + function UpdatingText({text, ms}) {
849 + const [step, _setStep] = useState(0);
850 + setStep = _setStep;
851 + const fullText = `${text}:${step}`;
852 + try {
853 + TextResource.read([fullText, ms]);
854 + ReactTestRenderer.unstable_yield(fullText);
855 + return fullText;
856 + } catch (promise) {
857 + if (typeof promise.then === 'function') {
858 + ReactTestRenderer.unstable_yield(`Suspend! [${fullText}]`);
859 + } else {
860 + ReactTestRenderer.unstable_yield(`Error! [${fullText}]`);
861 + }
862 + throw promise;
863 + }
864 + }
865 +
866 + root.update(
867 + <Suspense fallback={<Text text="Loading..." />}>
868 + <UpdatingText text="A" ms={1000} />
869 + </Suspense>,
870 + );
871 +
872 + expect(ReactTestRenderer).toHaveYielded(['Suspend! [A:0]', 'Loading...']);
873 + jest.advanceTimersByTime(1000);
874 + expect(ReactTestRenderer).toHaveYielded([
875 + 'Promise resolved [A:0]',
876 + 'A:0',
877 + ]);
878 + expect(root).toMatchRenderedOutput('A:0');
879 +
880 + setStep(1);
881 + expect(ReactTestRenderer).toHaveYielded(['Suspend! [A:1]', 'Loading...']);
882 + expect(root).toMatchRenderedOutput('Loading...');
883 +
884 + root.update(null);
885 + expect(root).toFlushWithoutYielding();
886 +
887 + jest.advanceTimersByTime(1000);
888 + });
889 });
890 });