Inline commitWork into commitMutationOnFiber
There's not really any reason these should be separate functions. The factoring has gotten sloppy and redundant because there's similar logic in both places, which is more obvious now that they're combined. Next I'll start combining the redundant branches.
Andrew Clark committed
Apr 7, 2022 at 19:09 UTC
e66e7a0fb875dac2d3e34c005c5be7503f979143
3 files changed
+320
-396
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+160
-197
@@ -68,13 +68,11 @@ import {
68
NoFlags,
69
ContentReset,
70
Placement,
71
- PlacementAndUpdate,
71
ChildDeletion,
72
Snapshot,
73
Update,
74
Ref,
75
Hydrating,
77
- HydratingAndUpdate,
76
Passive,
77
BeforeMutationMask,
78
MutationMask,
@@ -1799,156 +1797,6 @@ function commitDeletion(
1797
detachFiberMutation(current);
1798
}
1799
1802
-function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1803
- switch (finishedWork.tag) {
1804
- case FunctionComponent:
1805
- case ForwardRef:
1806
- case MemoComponent:
1807
- case SimpleMemoComponent: {
1808
- commitHookEffectListUnmount(
1809
- HookInsertion | HookHasEffect,
1810
- finishedWork,
1811
- finishedWork.return,
1812
- );
1813
- commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);
1814
- // Layout effects are destroyed during the mutation phase so that all
1815
- // destroy functions for all fibers are called before any create functions.
1816
- // This prevents sibling component effects from interfering with each other,
1817
- // e.g. a destroy function in one component should never override a ref set
1818
- // by a create function in another component during the same commit.
1819
- if (
1820
- enableProfilerTimer &&
1821
- enableProfilerCommitHooks &&
1822
- finishedWork.mode & ProfileMode
1823
- ) {
1824
- try {
1825
- startLayoutEffectTimer();
1826
- commitHookEffectListUnmount(
1827
- HookLayout | HookHasEffect,
1828
- finishedWork,
1829
- finishedWork.return,
1830
- );
1831
- } finally {
1832
- recordLayoutEffectDuration(finishedWork);
1833
- }
1834
- } else {
1835
- commitHookEffectListUnmount(
1836
- HookLayout | HookHasEffect,
1837
- finishedWork,
1838
- finishedWork.return,
1839
- );
1840
- }
1841
- return;
1842
- }
1843
- case ClassComponent: {
1844
- return;
1845
- }
1846
- case HostComponent: {
1847
- if (supportsMutation) {
1848
- const instance: Instance = finishedWork.stateNode;
1849
- if (instance != null) {
1850
- // Commit the work prepared earlier.
1851
- const newProps = finishedWork.memoizedProps;
1852
- // For hydration we reuse the update path but we treat the oldProps
1853
- // as the newProps. The updatePayload will contain the real change in
1854
- // this case.
1855
- const oldProps = current !== null ? current.memoizedProps : newProps;
1856
- const type = finishedWork.type;
1857
- // TODO: Type the updateQueue to be specific to host components.
1858
- const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any);
1859
- finishedWork.updateQueue = null;
1860
- if (updatePayload !== null) {
1861
- commitUpdate(
1862
- instance,
1863
- updatePayload,
1864
- type,
1865
- oldProps,
1866
- newProps,
1867
- finishedWork,
1868
- );
1869
- }
1870
- }
1871
- }
1872
- return;
1873
- }
1874
- case HostText: {
1875
- if (supportsMutation) {
1876
- if (finishedWork.stateNode === null) {
1877
- throw new Error(
1878
- 'This should have a text node initialized. This error is likely ' +
1879
- 'caused by a bug in React. Please file an issue.',
1880
- );
1881
- }
1882
-
1883
- const textInstance: TextInstance = finishedWork.stateNode;
1884
- const newText: string = finishedWork.memoizedProps;
1885
- // For hydration we reuse the update path but we treat the oldProps
1886
- // as the newProps. The updatePayload will contain the real change in
1887
- // this case.
1888
- const oldText: string =
1889
- current !== null ? current.memoizedProps : newText;
1890
- commitTextUpdate(textInstance, oldText, newText);
1891
- }
1892
- return;
1893
- }
1894
- case HostRoot: {
1895
- if (supportsMutation && supportsHydration) {
1896
- if (current !== null) {
1897
- const prevRootState: RootState = current.memoizedState;
1898
- if (prevRootState.isDehydrated) {
1899
- const root: FiberRoot = finishedWork.stateNode;
1900
- commitHydratedContainer(root.containerInfo);
1901
- }
1902
- }
1903
- }
1904
- if (supportsPersistence) {
1905
- const fiberRoot: FiberRoot = finishedWork.stateNode;
1906
- const containerInfo = fiberRoot.containerInfo;
1907
- const pendingChildren = fiberRoot.pendingChildren;
1908
- replaceContainerChildren(containerInfo, pendingChildren);
1909
- }
1910
- return;
1911
- }
1912
- case HostPortal: {
1913
- if (supportsPersistence) {
1914
- const portal = finishedWork.stateNode;
1915
- const containerInfo = portal.containerInfo;
1916
- const pendingChildren = portal.pendingChildren;
1917
- replaceContainerChildren(containerInfo, pendingChildren);
1918
- }
1919
- return;
1920
- }
1921
- case Profiler: {
1922
- return;
1923
- }
1924
- case SuspenseComponent: {
1925
- commitSuspenseCallback(finishedWork);
1926
- attachSuspenseRetryListeners(finishedWork);
1927
- return;
1928
- }
1929
- case SuspenseListComponent: {
1930
- attachSuspenseRetryListeners(finishedWork);
1931
- return;
1932
- }
1933
- case IncompleteClassComponent: {
1934
- return;
1935
- }
1936
- case ScopeComponent: {
1937
- if (enableScopeAPI) {
1938
- const scopeInstance = finishedWork.stateNode;
1939
- prepareScopeUpdate(scopeInstance, finishedWork);
1940
- return;
1941
- }
1942
- break;
1943
- }
1944
- }
1945
-
1946
- throw new Error(
1947
- 'This unit of work tag should not have side-effects. This error is ' +
1948
- 'likely caused by a bug in React. Please file an issue.',
1949
- );
1950
-}
1951
-
1800
function commitSuspenseCallback(finishedWork: Fiber) {
1801
// TODO: Move this to passive phase
1802
const newState: SuspenseState | null = finishedWork.memoizedState;
@@ -2133,6 +1981,7 @@ function commitMutationEffectsOnFiber(
1981
// switching on the type of work before checking the flags. That's what
1982
// we do in all the other phases. I think this one is only different
1983
// because of the shared reconciliation logic below.
1984
+ const current = finishedWork.alternate;
1985
const flags = finishedWork.flags;
1986
1987
if (flags & ContentReset) {
@@ -2140,7 +1989,6 @@ function commitMutationEffectsOnFiber(
1989
}
1990
1991
if (flags & Ref) {
2143
- const current = finishedWork.alternate;
1992
if (current !== null) {
1993
commitDetachRef(current);
1994
}
@@ -2159,7 +2007,6 @@ function commitMutationEffectsOnFiber(
2007
const newState: OffscreenState | null = finishedWork.memoizedState;
2008
const isHidden = newState !== null;
2009
if (isHidden) {
2162
- const current = finishedWork.alternate;
2010
const wasHidden = current !== null && current.memoizedState !== null;
2011
if (!wasHidden) {
2012
// TODO: Move to passive phase
@@ -2171,7 +2018,6 @@ function commitMutationEffectsOnFiber(
2018
case OffscreenComponent: {
2019
const newState: OffscreenState | null = finishedWork.memoizedState;
2020
const isHidden = newState !== null;
2174
- const current = finishedWork.alternate;
2021
const wasHidden = current !== null && current.memoizedState !== null;
2022
const offscreenBoundary: Fiber = finishedWork;
2023
@@ -2205,49 +2051,167 @@ function commitMutationEffectsOnFiber(
2051
}
2052
}
2053
2208
- // The following switch statement is only concerned about placement,
2209
- // updates, and deletions. To avoid needing to add a case for every possible
2210
- // bitmap value, we remove the secondary effects from the effect tag and
2211
- // switch on that value.
2212
- const primaryFlags = flags & (Placement | Update | Hydrating);
2213
- outer: switch (primaryFlags) {
2214
- case Placement: {
2215
- commitPlacement(finishedWork);
2216
- // Clear the "placement" from effect tag so that we know that this is
2217
- // inserted, before any life-cycles like componentDidMount gets called.
2218
- // TODO: findDOMNode doesn't rely on this any more but isMounted does
2219
- // and isMounted is deprecated anyway so we should be able to kill this.
2220
- finishedWork.flags &= ~Placement;
2221
- break;
2222
- }
2223
- case PlacementAndUpdate: {
2224
- // Placement
2225
- commitPlacement(finishedWork);
2226
- // Clear the "placement" from effect tag so that we know that this is
2227
- // inserted, before any life-cycles like componentDidMount gets called.
2228
- finishedWork.flags &= ~Placement;
2054
+ // These are related to reconciliation so they affect every fiber type; that's
2055
+ // why they aren't in the main switch statement below.
2056
+ if (flags & Placement) {
2057
+ commitPlacement(finishedWork);
2058
+ // Clear the "placement" from effect tag so that we know that this is
2059
+ // inserted, before any life-cycles like componentDidMount gets called.
2060
+ // TODO: findDOMNode doesn't rely on this any more but isMounted does
2061
+ // and isMounted is deprecated anyway so we should be able to kill this.
2062
+ finishedWork.flags &= ~Placement;
2063
+ }
2064
+ if (flags & Hydrating) {
2065
+ finishedWork.flags &= ~Hydrating;
2066
+ }
2067
2230
- // Update
2231
- const current = finishedWork.alternate;
2232
- commitWork(current, finishedWork);
2233
- break;
2234
- }
2235
- case Hydrating: {
2236
- finishedWork.flags &= ~Hydrating;
2237
- break;
2238
- }
2239
- case HydratingAndUpdate: {
2240
- finishedWork.flags &= ~Hydrating;
2068
+ // TODO: Move the ad-hoc flag checks above into the main switch statement.
2069
+ if (flags & Update) {
2070
+ switch (finishedWork.tag) {
2071
+ case FunctionComponent:
2072
+ case ForwardRef:
2073
+ case MemoComponent:
2074
+ case SimpleMemoComponent: {
2075
+ commitHookEffectListUnmount(
2076
+ HookInsertion | HookHasEffect,
2077
+ finishedWork,
2078
+ finishedWork.return,
2079
+ );
2080
+ commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);
2081
+ // Layout effects are destroyed during the mutation phase so that all
2082
+ // destroy functions for all fibers are called before any create functions.
2083
+ // This prevents sibling component effects from interfering with each other,
2084
+ // e.g. a destroy function in one component should never override a ref set
2085
+ // by a create function in another component during the same commit.
2086
+ if (
2087
+ enableProfilerTimer &&
2088
+ enableProfilerCommitHooks &&
2089
+ finishedWork.mode & ProfileMode
2090
+ ) {
2091
+ try {
2092
+ startLayoutEffectTimer();
2093
+ commitHookEffectListUnmount(
2094
+ HookLayout | HookHasEffect,
2095
+ finishedWork,
2096
+ finishedWork.return,
2097
+ );
2098
+ } finally {
2099
+ recordLayoutEffectDuration(finishedWork);
2100
+ }
2101
+ } else {
2102
+ commitHookEffectListUnmount(
2103
+ HookLayout | HookHasEffect,
2104
+ finishedWork,
2105
+ finishedWork.return,
2106
+ );
2107
+ }
2108
+ return;
2109
+ }
2110
+ case ClassComponent: {
2111
+ return;
2112
+ }
2113
+ case HostComponent: {
2114
+ if (supportsMutation) {
2115
+ const instance: Instance = finishedWork.stateNode;
2116
+ if (instance != null) {
2117
+ // Commit the work prepared earlier.
2118
+ const newProps = finishedWork.memoizedProps;
2119
+ // For hydration we reuse the update path but we treat the oldProps
2120
+ // as the newProps. The updatePayload will contain the real change in
2121
+ // this case.
2122
+ const oldProps =
2123
+ current !== null ? current.memoizedProps : newProps;
2124
+ const type = finishedWork.type;
2125
+ // TODO: Type the updateQueue to be specific to host components.
2126
+ const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any);
2127
+ finishedWork.updateQueue = null;
2128
+ if (updatePayload !== null) {
2129
+ commitUpdate(
2130
+ instance,
2131
+ updatePayload,
2132
+ type,
2133
+ oldProps,
2134
+ newProps,
2135
+ finishedWork,
2136
+ );
2137
+ }
2138
+ }
2139
+ }
2140
+ return;
2141
+ }
2142
+ case HostText: {
2143
+ if (supportsMutation) {
2144
+ if (finishedWork.stateNode === null) {
2145
+ throw new Error(
2146
+ 'This should have a text node initialized. This error is likely ' +
2147
+ 'caused by a bug in React. Please file an issue.',
2148
+ );
2149
+ }
2150
2242
- // Update
2243
- const current = finishedWork.alternate;
2244
- commitWork(current, finishedWork);
2245
- break;
2246
- }
2247
- case Update: {
2248
- const current = finishedWork.alternate;
2249
- commitWork(current, finishedWork);
2250
- break;
2151
+ const textInstance: TextInstance = finishedWork.stateNode;
2152
+ const newText: string = finishedWork.memoizedProps;
2153
+ // For hydration we reuse the update path but we treat the oldProps
2154
+ // as the newProps. The updatePayload will contain the real change in
2155
+ // this case.
2156
+ const oldText: string =
2157
+ current !== null ? current.memoizedProps : newText;
2158
+ commitTextUpdate(textInstance, oldText, newText);
2159
+ }
2160
+ return;
2161
+ }
2162
+ case HostRoot: {
2163
+ if (supportsMutation && supportsHydration) {
2164
+ if (current !== null) {
2165
+ const prevRootState: RootState = current.memoizedState;
2166
+ if (prevRootState.isDehydrated) {
2167
+ commitHydratedContainer(root.containerInfo);
2168
+ }
2169
+ }
2170
+ }
2171
+ if (supportsPersistence) {
2172
+ const containerInfo = root.containerInfo;
2173
+ const pendingChildren = root.pendingChildren;
2174
+ replaceContainerChildren(containerInfo, pendingChildren);
2175
+ }
2176
+ return;
2177
+ }
2178
+ case HostPortal: {
2179
+ if (supportsPersistence) {
2180
+ const portal = finishedWork.stateNode;
2181
+ const containerInfo = portal.containerInfo;
2182
+ const pendingChildren = portal.pendingChildren;
2183
+ replaceContainerChildren(containerInfo, pendingChildren);
2184
+ }
2185
+ return;
2186
+ }
2187
+ case Profiler: {
2188
+ return;
2189
+ }
2190
+ case SuspenseComponent: {
2191
+ commitSuspenseCallback(finishedWork);
2192
+ attachSuspenseRetryListeners(finishedWork);
2193
+ return;
2194
+ }
2195
+ case SuspenseListComponent: {
2196
+ attachSuspenseRetryListeners(finishedWork);
2197
+ return;
2198
+ }
2199
+ case IncompleteClassComponent: {
2200
+ return;
2201
+ }
2202
+ case ScopeComponent: {
2203
+ if (enableScopeAPI) {
2204
+ const scopeInstance = finishedWork.stateNode;
2205
+ prepareScopeUpdate(scopeInstance, finishedWork);
2206
+ }
2207
+ return;
2208
+ }
2209
+ default: {
2210
+ throw new Error(
2211
+ 'This unit of work tag should not have side-effects. This error is ' +
2212
+ 'likely caused by a bug in React. Please file an issue.',
2213
+ );
2214
+ }
2215
}
2216
}
2217
}
@@ -3056,7 +3020,6 @@ export {
3020
commitResetTextContent,
3021
commitPlacement,
3022
commitDeletion,
3059
- commitWork,
3023
commitAttachRef,
3024
commitDetachRef,
3025
invokeLayoutEffectMountInDEV,
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+160
-197
@@ -68,13 +68,11 @@ import {
68
NoFlags,
69
ContentReset,
70
Placement,
71
- PlacementAndUpdate,
71
ChildDeletion,
72
Snapshot,
73
Update,
74
Ref,
75
Hydrating,
77
- HydratingAndUpdate,
76
Passive,
77
BeforeMutationMask,
78
MutationMask,
@@ -1799,156 +1797,6 @@ function commitDeletion(
1797
detachFiberMutation(current);
1798
}
1799
1802
-function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1803
- switch (finishedWork.tag) {
1804
- case FunctionComponent:
1805
- case ForwardRef:
1806
- case MemoComponent:
1807
- case SimpleMemoComponent: {
1808
- commitHookEffectListUnmount(
1809
- HookInsertion | HookHasEffect,
1810
- finishedWork,
1811
- finishedWork.return,
1812
- );
1813
- commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);
1814
- // Layout effects are destroyed during the mutation phase so that all
1815
- // destroy functions for all fibers are called before any create functions.
1816
- // This prevents sibling component effects from interfering with each other,
1817
- // e.g. a destroy function in one component should never override a ref set
1818
- // by a create function in another component during the same commit.
1819
- if (
1820
- enableProfilerTimer &&
1821
- enableProfilerCommitHooks &&
1822
- finishedWork.mode & ProfileMode
1823
- ) {
1824
- try {
1825
- startLayoutEffectTimer();
1826
- commitHookEffectListUnmount(
1827
- HookLayout | HookHasEffect,
1828
- finishedWork,
1829
- finishedWork.return,
1830
- );
1831
- } finally {
1832
- recordLayoutEffectDuration(finishedWork);
1833
- }
1834
- } else {
1835
- commitHookEffectListUnmount(
1836
- HookLayout | HookHasEffect,
1837
- finishedWork,
1838
- finishedWork.return,
1839
- );
1840
- }
1841
- return;
1842
- }
1843
- case ClassComponent: {
1844
- return;
1845
- }
1846
- case HostComponent: {
1847
- if (supportsMutation) {
1848
- const instance: Instance = finishedWork.stateNode;
1849
- if (instance != null) {
1850
- // Commit the work prepared earlier.
1851
- const newProps = finishedWork.memoizedProps;
1852
- // For hydration we reuse the update path but we treat the oldProps
1853
- // as the newProps. The updatePayload will contain the real change in
1854
- // this case.
1855
- const oldProps = current !== null ? current.memoizedProps : newProps;
1856
- const type = finishedWork.type;
1857
- // TODO: Type the updateQueue to be specific to host components.
1858
- const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any);
1859
- finishedWork.updateQueue = null;
1860
- if (updatePayload !== null) {
1861
- commitUpdate(
1862
- instance,
1863
- updatePayload,
1864
- type,
1865
- oldProps,
1866
- newProps,
1867
- finishedWork,
1868
- );
1869
- }
1870
- }
1871
- }
1872
- return;
1873
- }
1874
- case HostText: {
1875
- if (supportsMutation) {
1876
- if (finishedWork.stateNode === null) {
1877
- throw new Error(
1878
- 'This should have a text node initialized. This error is likely ' +
1879
- 'caused by a bug in React. Please file an issue.',
1880
- );
1881
- }
1882
-
1883
- const textInstance: TextInstance = finishedWork.stateNode;
1884
- const newText: string = finishedWork.memoizedProps;
1885
- // For hydration we reuse the update path but we treat the oldProps
1886
- // as the newProps. The updatePayload will contain the real change in
1887
- // this case.
1888
- const oldText: string =
1889
- current !== null ? current.memoizedProps : newText;
1890
- commitTextUpdate(textInstance, oldText, newText);
1891
- }
1892
- return;
1893
- }
1894
- case HostRoot: {
1895
- if (supportsMutation && supportsHydration) {
1896
- if (current !== null) {
1897
- const prevRootState: RootState = current.memoizedState;
1898
- if (prevRootState.isDehydrated) {
1899
- const root: FiberRoot = finishedWork.stateNode;
1900
- commitHydratedContainer(root.containerInfo);
1901
- }
1902
- }
1903
- }
1904
- if (supportsPersistence) {
1905
- const fiberRoot: FiberRoot = finishedWork.stateNode;
1906
- const containerInfo = fiberRoot.containerInfo;
1907
- const pendingChildren = fiberRoot.pendingChildren;
1908
- replaceContainerChildren(containerInfo, pendingChildren);
1909
- }
1910
- return;
1911
- }
1912
- case HostPortal: {
1913
- if (supportsPersistence) {
1914
- const portal = finishedWork.stateNode;
1915
- const containerInfo = portal.containerInfo;
1916
- const pendingChildren = portal.pendingChildren;
1917
- replaceContainerChildren(containerInfo, pendingChildren);
1918
- }
1919
- return;
1920
- }
1921
- case Profiler: {
1922
- return;
1923
- }
1924
- case SuspenseComponent: {
1925
- commitSuspenseCallback(finishedWork);
1926
- attachSuspenseRetryListeners(finishedWork);
1927
- return;
1928
- }
1929
- case SuspenseListComponent: {
1930
- attachSuspenseRetryListeners(finishedWork);
1931
- return;
1932
- }
1933
- case IncompleteClassComponent: {
1934
- return;
1935
- }
1936
- case ScopeComponent: {
1937
- if (enableScopeAPI) {
1938
- const scopeInstance = finishedWork.stateNode;
1939
- prepareScopeUpdate(scopeInstance, finishedWork);
1940
- return;
1941
- }
1942
- break;
1943
- }
1944
- }
1945
-
1946
- throw new Error(
1947
- 'This unit of work tag should not have side-effects. This error is ' +
1948
- 'likely caused by a bug in React. Please file an issue.',
1949
- );
1950
-}
1951
-
1800
function commitSuspenseCallback(finishedWork: Fiber) {
1801
// TODO: Move this to passive phase
1802
const newState: SuspenseState | null = finishedWork.memoizedState;
@@ -2133,6 +1981,7 @@ function commitMutationEffectsOnFiber(
1981
// switching on the type of work before checking the flags. That's what
1982
// we do in all the other phases. I think this one is only different
1983
// because of the shared reconciliation logic below.
1984
+ const current = finishedWork.alternate;
1985
const flags = finishedWork.flags;
1986
1987
if (flags & ContentReset) {
@@ -2140,7 +1989,6 @@ function commitMutationEffectsOnFiber(
1989
}
1990
1991
if (flags & Ref) {
2143
- const current = finishedWork.alternate;
1992
if (current !== null) {
1993
commitDetachRef(current);
1994
}
@@ -2159,7 +2007,6 @@ function commitMutationEffectsOnFiber(
2007
const newState: OffscreenState | null = finishedWork.memoizedState;
2008
const isHidden = newState !== null;
2009
if (isHidden) {
2162
- const current = finishedWork.alternate;
2010
const wasHidden = current !== null && current.memoizedState !== null;
2011
if (!wasHidden) {
2012
// TODO: Move to passive phase
@@ -2171,7 +2018,6 @@ function commitMutationEffectsOnFiber(
2018
case OffscreenComponent: {
2019
const newState: OffscreenState | null = finishedWork.memoizedState;
2020
const isHidden = newState !== null;
2174
- const current = finishedWork.alternate;
2021
const wasHidden = current !== null && current.memoizedState !== null;
2022
const offscreenBoundary: Fiber = finishedWork;
2023
@@ -2205,49 +2051,167 @@ function commitMutationEffectsOnFiber(
2051
}
2052
}
2053
2208
- // The following switch statement is only concerned about placement,
2209
- // updates, and deletions. To avoid needing to add a case for every possible
2210
- // bitmap value, we remove the secondary effects from the effect tag and
2211
- // switch on that value.
2212
- const primaryFlags = flags & (Placement | Update | Hydrating);
2213
- outer: switch (primaryFlags) {
2214
- case Placement: {
2215
- commitPlacement(finishedWork);
2216
- // Clear the "placement" from effect tag so that we know that this is
2217
- // inserted, before any life-cycles like componentDidMount gets called.
2218
- // TODO: findDOMNode doesn't rely on this any more but isMounted does
2219
- // and isMounted is deprecated anyway so we should be able to kill this.
2220
- finishedWork.flags &= ~Placement;
2221
- break;
2222
- }
2223
- case PlacementAndUpdate: {
2224
- // Placement
2225
- commitPlacement(finishedWork);
2226
- // Clear the "placement" from effect tag so that we know that this is
2227
- // inserted, before any life-cycles like componentDidMount gets called.
2228
- finishedWork.flags &= ~Placement;
2054
+ // These are related to reconciliation so they affect every fiber type; that's
2055
+ // why they aren't in the main switch statement below.
2056
+ if (flags & Placement) {
2057
+ commitPlacement(finishedWork);
2058
+ // Clear the "placement" from effect tag so that we know that this is
2059
+ // inserted, before any life-cycles like componentDidMount gets called.
2060
+ // TODO: findDOMNode doesn't rely on this any more but isMounted does
2061
+ // and isMounted is deprecated anyway so we should be able to kill this.
2062
+ finishedWork.flags &= ~Placement;
2063
+ }
2064
+ if (flags & Hydrating) {
2065
+ finishedWork.flags &= ~Hydrating;
2066
+ }
2067
2230
- // Update
2231
- const current = finishedWork.alternate;
2232
- commitWork(current, finishedWork);
2233
- break;
2234
- }
2235
- case Hydrating: {
2236
- finishedWork.flags &= ~Hydrating;
2237
- break;
2238
- }
2239
- case HydratingAndUpdate: {
2240
- finishedWork.flags &= ~Hydrating;
2068
+ // TODO: Move the ad-hoc flag checks above into the main switch statement.
2069
+ if (flags & Update) {
2070
+ switch (finishedWork.tag) {
2071
+ case FunctionComponent:
2072
+ case ForwardRef:
2073
+ case MemoComponent:
2074
+ case SimpleMemoComponent: {
2075
+ commitHookEffectListUnmount(
2076
+ HookInsertion | HookHasEffect,
2077
+ finishedWork,
2078
+ finishedWork.return,
2079
+ );
2080
+ commitHookEffectListMount(HookInsertion | HookHasEffect, finishedWork);
2081
+ // Layout effects are destroyed during the mutation phase so that all
2082
+ // destroy functions for all fibers are called before any create functions.
2083
+ // This prevents sibling component effects from interfering with each other,
2084
+ // e.g. a destroy function in one component should never override a ref set
2085
+ // by a create function in another component during the same commit.
2086
+ if (
2087
+ enableProfilerTimer &&
2088
+ enableProfilerCommitHooks &&
2089
+ finishedWork.mode & ProfileMode
2090
+ ) {
2091
+ try {
2092
+ startLayoutEffectTimer();
2093
+ commitHookEffectListUnmount(
2094
+ HookLayout | HookHasEffect,
2095
+ finishedWork,
2096
+ finishedWork.return,
2097
+ );
2098
+ } finally {
2099
+ recordLayoutEffectDuration(finishedWork);
2100
+ }
2101
+ } else {
2102
+ commitHookEffectListUnmount(
2103
+ HookLayout | HookHasEffect,
2104
+ finishedWork,
2105
+ finishedWork.return,
2106
+ );
2107
+ }
2108
+ return;
2109
+ }
2110
+ case ClassComponent: {
2111
+ return;
2112
+ }
2113
+ case HostComponent: {
2114
+ if (supportsMutation) {
2115
+ const instance: Instance = finishedWork.stateNode;
2116
+ if (instance != null) {
2117
+ // Commit the work prepared earlier.
2118
+ const newProps = finishedWork.memoizedProps;
2119
+ // For hydration we reuse the update path but we treat the oldProps
2120
+ // as the newProps. The updatePayload will contain the real change in
2121
+ // this case.
2122
+ const oldProps =
2123
+ current !== null ? current.memoizedProps : newProps;
2124
+ const type = finishedWork.type;
2125
+ // TODO: Type the updateQueue to be specific to host components.
2126
+ const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any);
2127
+ finishedWork.updateQueue = null;
2128
+ if (updatePayload !== null) {
2129
+ commitUpdate(
2130
+ instance,
2131
+ updatePayload,
2132
+ type,
2133
+ oldProps,
2134
+ newProps,
2135
+ finishedWork,
2136
+ );
2137
+ }
2138
+ }
2139
+ }
2140
+ return;
2141
+ }
2142
+ case HostText: {
2143
+ if (supportsMutation) {
2144
+ if (finishedWork.stateNode === null) {
2145
+ throw new Error(
2146
+ 'This should have a text node initialized. This error is likely ' +
2147
+ 'caused by a bug in React. Please file an issue.',
2148
+ );
2149
+ }
2150
2242
- // Update
2243
- const current = finishedWork.alternate;
2244
- commitWork(current, finishedWork);
2245
- break;
2246
- }
2247
- case Update: {
2248
- const current = finishedWork.alternate;
2249
- commitWork(current, finishedWork);
2250
- break;
2151
+ const textInstance: TextInstance = finishedWork.stateNode;
2152
+ const newText: string = finishedWork.memoizedProps;
2153
+ // For hydration we reuse the update path but we treat the oldProps
2154
+ // as the newProps. The updatePayload will contain the real change in
2155
+ // this case.
2156
+ const oldText: string =
2157
+ current !== null ? current.memoizedProps : newText;
2158
+ commitTextUpdate(textInstance, oldText, newText);
2159
+ }
2160
+ return;
2161
+ }
2162
+ case HostRoot: {
2163
+ if (supportsMutation && supportsHydration) {
2164
+ if (current !== null) {
2165
+ const prevRootState: RootState = current.memoizedState;
2166
+ if (prevRootState.isDehydrated) {
2167
+ commitHydratedContainer(root.containerInfo);
2168
+ }
2169
+ }
2170
+ }
2171
+ if (supportsPersistence) {
2172
+ const containerInfo = root.containerInfo;
2173
+ const pendingChildren = root.pendingChildren;
2174
+ replaceContainerChildren(containerInfo, pendingChildren);
2175
+ }
2176
+ return;
2177
+ }
2178
+ case HostPortal: {
2179
+ if (supportsPersistence) {
2180
+ const portal = finishedWork.stateNode;
2181
+ const containerInfo = portal.containerInfo;
2182
+ const pendingChildren = portal.pendingChildren;
2183
+ replaceContainerChildren(containerInfo, pendingChildren);
2184
+ }
2185
+ return;
2186
+ }
2187
+ case Profiler: {
2188
+ return;
2189
+ }
2190
+ case SuspenseComponent: {
2191
+ commitSuspenseCallback(finishedWork);
2192
+ attachSuspenseRetryListeners(finishedWork);
2193
+ return;
2194
+ }
2195
+ case SuspenseListComponent: {
2196
+ attachSuspenseRetryListeners(finishedWork);
2197
+ return;
2198
+ }
2199
+ case IncompleteClassComponent: {
2200
+ return;
2201
+ }
2202
+ case ScopeComponent: {
2203
+ if (enableScopeAPI) {
2204
+ const scopeInstance = finishedWork.stateNode;
2205
+ prepareScopeUpdate(scopeInstance, finishedWork);
2206
+ }
2207
+ return;
2208
+ }
2209
+ default: {
2210
+ throw new Error(
2211
+ 'This unit of work tag should not have side-effects. This error is ' +
2212
+ 'likely caused by a bug in React. Please file an issue.',
2213
+ );
2214
+ }
2215
}
2216
}
2217
}
@@ -3056,7 +3020,6 @@ export {
3020
commitResetTextContent,
3021
commitPlacement,
3022
commitDeletion,
3059
- commitWork,
3023
commitAttachRef,
3024
commitDetachRef,
3025
invokeLayoutEffectMountInDEV,
packages/react-reconciler/src/ReactFiberFlags.js
-2
@@ -18,7 +18,6 @@ export const PerformedWork = /* */ 0b00000000000000000000000001;
18
// You can change the rest (and add more).
19
export const Placement = /* */ 0b00000000000000000000000010;
20
export const Update = /* */ 0b00000000000000000000000100;
21
-export const PlacementAndUpdate = /* */ Placement | Update;
21
export const Deletion = /* */ 0b00000000000000000000001000;
22
export const ChildDeletion = /* */ 0b00000000000000000000010000;
23
export const ContentReset = /* */ 0b00000000000000000000100000;
@@ -29,7 +28,6 @@ export const Ref = /* */ 0b00000000000000001000000000;
28
export const Snapshot = /* */ 0b00000000000000010000000000;
29
export const Passive = /* */ 0b00000000000000100000000000;
30
export const Hydrating = /* */ 0b00000000000001000000000000;
32
-export const HydratingAndUpdate = /* */ Hydrating | Update;
31
export const Visibility = /* */ 0b00000000000010000000000000;
32
export const StoreConsistency = /* */ 0b00000000000100000000000000;
33