diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts
index 44e65063ec..01f88d4b8a 100644
--- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts
+++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidateNoDerivedComputationsInEffects.ts
@@ -300,6 +300,19 @@ function validateEffect(
sourceIds: argMetadata.sourcesIds,
});
}
+ } else if (instr.value.kind === 'CallExpression') {
+ const calleeMetadata = derivationCache.get(
+ instr.value.callee.identifier.id,
+ );
+
+ if (
+ calleeMetadata !== undefined &&
+ (calleeMetadata.typeOfValue === 'fromProps' ||
+ calleeMetadata.typeOfValue === 'fromPropsAndState')
+ ) {
+ // If the callee is a prop we can't confidently say that it should be derived in render
+ return;
+ }
}
}
seenBlocks.add(block.id);
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.expect.md
new file mode 100644
index 0000000000..afae2c20a6
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.expect.md
@@ -0,0 +1,75 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({propValue, onChange}) {
+ const [value, setValue] = useState(null);
+ useEffect(() => {
+ setValue(propValue);
+ onChange();
+ }, [propValue]);
+
+ return
{value}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test', onChange: () => {}}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+function Component(t0) {
+ const $ = _c(7);
+ const { propValue, onChange } = t0;
+ const [value, setValue] = useState(null);
+ let t1;
+ if ($[0] !== onChange || $[1] !== propValue) {
+ t1 = () => {
+ setValue(propValue);
+ onChange();
+ };
+ $[0] = onChange;
+ $[1] = propValue;
+ $[2] = t1;
+ } else {
+ t1 = $[2];
+ }
+ let t2;
+ if ($[3] !== propValue) {
+ t2 = [propValue];
+ $[3] = propValue;
+ $[4] = t2;
+ } else {
+ t2 = $[4];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[5] !== value) {
+ t3 = {value}
;
+ $[5] = value;
+ $[6] = t3;
+ } else {
+ t3 = $[6];
+ }
+ return t3;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ propValue: "test", onChange: () => {} }],
+};
+
+```
+
+### Eval output
+(kind: ok) test
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-contains-prop-function-call-no-error.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.js
similarity index 100%
rename from compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-contains-prop-function-call-no-error.js
rename to compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-prop-function-call-no-error.js
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-contains-prop-function-call-no-error.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-contains-prop-function-call-no-error.expect.md
deleted file mode 100644
index 31b7114af5..0000000000
--- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-contains-prop-function-call-no-error.expect.md
+++ /dev/null
@@ -1,43 +0,0 @@
-
-## Input
-
-```javascript
-// @validateNoDerivedComputationsInEffects
-import {useEffect, useState} from 'react';
-
-function Component({propValue, onChange}) {
- const [value, setValue] = useState(null);
- useEffect(() => {
- setValue(propValue);
- onChange();
- }, [propValue]);
-
- return {value}
;
-}
-
-export const FIXTURE_ENTRYPOINT = {
- fn: Component,
- params: [{propValue: 'test', onChange: () => {}}],
-};
-
-```
-
-
-## Error
-
-```
-Found 1 error:
-
-Error: Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)
-
-error.effect-contains-prop-function-call-no-error.ts:7:4
- 5 | const [value, setValue] = useState(null);
- 6 | useEffect(() => {
-> 7 | setValue(propValue);
- | ^^^^^^^^^^^^^^^^^^^ Values derived from props and state should be calculated during render, not in an effect. (https://react.dev/learn/you-might-not-need-an-effect#updating-state-based-on-props-or-state)
- 8 | onChange();
- 9 | }, [propValue]);
- 10 |
-```
-
-
\ No newline at end of file