You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[compiler] Fix false negatives and add data flow tree to compiler error for no-deriving-state-in-effects (#34995)
Summary:
Revamped the derivationCache graph.
This fixes a bunch of bugs where sometimes we fail to track from which
props/state we derived values from.
Also, it is more intuitive and allows us to easily implement a Data Flow
Tree.
We can print this tree which gives insight on how the data is derived
and should facilitate error resolution in complicated components
Test Plan:
Added a test case where we were failing to track derivations. Also
updated the test cases with the new error containing the data flow tree
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34995).
* #35044
* #35020
* #34973
* #34972
* __->__ #34995
* #34967
Copy file name to clipboardExpand all lines: compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects_exp.ts
description=`From local state: [${derivedDepsStr}]`;
530
-
}else{
531
-
description=`From props and local state: [${derivedDepsStr}]`;
630
+
constpropsSet=newSet<string>();
631
+
conststateSet=newSet<string>();
632
+
633
+
constrootNodesMap=newMap<string,TreeNode>();
634
+
for(constidofderivedSetStateCall.sourceIds){
635
+
constnodes=buildTreeNode(id,context);
636
+
for(constnodeofnodes){
637
+
if(!rootNodesMap.has(node.name)){
638
+
rootNodesMap.set(node.name,node);
639
+
}
640
+
}
641
+
}
642
+
constrootNodes=Array.from(rootNodesMap.values());
643
+
644
+
consttrees=rootNodes.map((node,index)=>
645
+
renderTree(
646
+
node,
647
+
'',
648
+
index===rootNodes.length-1,
649
+
propsSet,
650
+
stateSet,
651
+
),
652
+
);
653
+
654
+
constpropsArr=Array.from(propsSet);
655
+
conststateArr=Array.from(stateSet);
656
+
657
+
letrootSources='';
658
+
if(propsArr.length>0){
659
+
rootSources+=`Props: [${propsArr.join(', ')}]`;
532
660
}
661
+
if(stateArr.length>0){
662
+
if(rootSources)rootSources+='\n';
663
+
rootSources+=`State: [${stateArr.join(', ')}]`;
664
+
}
665
+
666
+
constdescription=`Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user
667
+
668
+
This setState call is setting a derived value that depends on the following reactive sources:
description: `Derived values (${description}) should be computed during render, rather than in effects. Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user`,
679
+
description: description,
537
680
category: ErrorCategory.EffectDerivationsOfState,
538
681
reason:
539
682
'You might not need an effect. Derive values in render, not effects.',
Copy file name to clipboardExpand all lines: compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-conditionally-in-effect.expect.md
+10-1Lines changed: 10 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,7 +34,16 @@ Found 1 error:
34
34
35
35
Error: You might not need an effect. Derive values in render, not effects.
36
36
37
-
Derived values (From props: [value]) should be computed during render, rather than in effects. Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user.
37
+
Using an effect triggers an additional render which can hurt performance and user experience, potentially briefly showing stale values to the user
38
+
39
+
This setState call is setting a derived value that depends on the following reactive sources:
0 commit comments