diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.expect.md
new file mode 100644
index 0000000000..b7a1c85d52
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.expect.md
@@ -0,0 +1,79 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({value, enabled}) {
+ const [localValue, setLocalValue] = useState('');
+
+ useEffect(() => {
+ if (enabled) {
+ setLocalValue(value);
+ } else {
+ setLocalValue('disabled');
+ }
+ }, [value, enabled]);
+
+ return
{localValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{value: 'test', enabled: true}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+function Component(t0) {
+ const $ = _c(6);
+ const { value, enabled } = t0;
+ const [localValue, setLocalValue] = useState("");
+ let t1;
+ let t2;
+ if ($[0] !== enabled || $[1] !== value) {
+ t1 = () => {
+ if (enabled) {
+ setLocalValue(value);
+ } else {
+ setLocalValue("disabled");
+ }
+ };
+
+ t2 = [value, enabled];
+ $[0] = enabled;
+ $[1] = value;
+ $[2] = t1;
+ $[3] = t2;
+ } else {
+ t1 = $[2];
+ t2 = $[3];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[4] !== localValue) {
+ t3 = {localValue}
;
+ $[4] = localValue;
+ $[5] = t3;
+ } else {
+ t3 = $[5];
+ }
+ return t3;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ value: "test", enabled: true }],
+};
+
+```
+
+### 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/derived-state-conditionally-in-effect.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.js
new file mode 100644
index 0000000000..79d83b8925
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-conditionally-in-effect.js
@@ -0,0 +1,21 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({value, enabled}) {
+ const [localValue, setLocalValue] = useState('');
+
+ useEffect(() => {
+ if (enabled) {
+ setLocalValue(value);
+ } else {
+ setLocalValue('disabled');
+ }
+ }, [value, enabled]);
+
+ return {localValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{value: 'test', enabled: true}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.expect.md
new file mode 100644
index 0000000000..d4024eab5c
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.expect.md
@@ -0,0 +1,68 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+
+export default function Component(input = 'empty') {
+ const [currInput, setCurrInput] = useState(input);
+ const localConst = 'local const';
+
+ useEffect(() => {
+ setCurrInput(input + localConst);
+ }, [input, localConst]);
+
+ return {currInput}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{input: 'test'}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+
+export default function Component(t0) {
+ const $ = _c(5);
+ const input = t0 === undefined ? "empty" : t0;
+ const [currInput, setCurrInput] = useState(input);
+ let t1;
+ let t2;
+ if ($[0] !== input) {
+ t1 = () => {
+ setCurrInput(input + "local const");
+ };
+ t2 = [input, "local const"];
+ $[0] = input;
+ $[1] = t1;
+ $[2] = t2;
+ } else {
+ t1 = $[1];
+ t2 = $[2];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[3] !== currInput) {
+ t3 = {currInput}
;
+ $[3] = currInput;
+ $[4] = t3;
+ } else {
+ t3 = $[4];
+ }
+ return t3;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ input: "test" }],
+};
+
+```
+
+### Eval output
+(kind: exception) useState is not defined
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.js
new file mode 100644
index 0000000000..20a646f1ff
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-default-props.js
@@ -0,0 +1,17 @@
+// @validateNoDerivedComputationsInEffects
+
+export default function Component(input = 'empty') {
+ const [currInput, setCurrInput] = useState(input);
+ const localConst = 'local const';
+
+ useEffect(() => {
+ setCurrInput(input + localConst);
+ }, [input, localConst]);
+
+ return {currInput}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{input: 'test'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.expect.md
new file mode 100644
index 0000000000..932e4fc9cc
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.expect.md
@@ -0,0 +1,108 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({firstName}) {
+ const [lastName, setLastName] = useState('Doe');
+ const [fullName, setFullName] = useState('John');
+
+ const middleName = 'D.';
+
+ useEffect(() => {
+ setFullName(firstName + ' ' + middleName + ' ' + lastName);
+ }, [firstName, middleName, lastName]);
+
+ return (
+
+
setLastName(e.target.value)} />
+
{fullName}
+
+ );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{firstName: 'John'}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+function Component(t0) {
+ const $ = _c(12);
+ const { firstName } = t0;
+ const [lastName, setLastName] = useState("Doe");
+ const [fullName, setFullName] = useState("John");
+ let t1;
+ let t2;
+ if ($[0] !== firstName || $[1] !== lastName) {
+ t1 = () => {
+ setFullName(firstName + " " + "D." + " " + lastName);
+ };
+ t2 = [firstName, "D.", lastName];
+ $[0] = firstName;
+ $[1] = lastName;
+ $[2] = t1;
+ $[3] = t2;
+ } else {
+ t1 = $[2];
+ t2 = $[3];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
+ t3 = (e) => setLastName(e.target.value);
+ $[4] = t3;
+ } else {
+ t3 = $[4];
+ }
+ let t4;
+ if ($[5] !== lastName) {
+ t4 = ;
+ $[5] = lastName;
+ $[6] = t4;
+ } else {
+ t4 = $[6];
+ }
+ let t5;
+ if ($[7] !== fullName) {
+ t5 = {fullName}
;
+ $[7] = fullName;
+ $[8] = t5;
+ } else {
+ t5 = $[8];
+ }
+ let t6;
+ if ($[9] !== t4 || $[10] !== t5) {
+ t6 = (
+
+ {t4}
+ {t5}
+
+ );
+ $[9] = t4;
+ $[10] = t5;
+ $[11] = t6;
+ } else {
+ t6 = $[11];
+ }
+ return t6;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ firstName: "John" }],
+};
+
+```
+
+### Eval output
+(kind: ok)
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.js
new file mode 100644
index 0000000000..4b1f7222e7
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-local-state-and-component-scope.js
@@ -0,0 +1,25 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({firstName}) {
+ const [lastName, setLastName] = useState('Doe');
+ const [fullName, setFullName] = useState('John');
+
+ const middleName = 'D.';
+
+ useEffect(() => {
+ setFullName(firstName + ' ' + middleName + ' ' + lastName);
+ }, [firstName, middleName, lastName]);
+
+ return (
+
+
setLastName(e.target.value)} />
+
{fullName}
+
+ );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{firstName: 'John'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.expect.md
new file mode 100644
index 0000000000..cc98724820
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.expect.md
@@ -0,0 +1,69 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+
+function Component({value}) {
+ const [localValue, setLocalValue] = useState('');
+
+ useEffect(() => {
+ setLocalValue(value);
+ document.title = `Value: ${value}`;
+ }, [value]);
+
+ return {localValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{value: 'test'}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+
+function Component(t0) {
+ const $ = _c(5);
+ const { value } = t0;
+ const [localValue, setLocalValue] = useState("");
+ let t1;
+ let t2;
+ if ($[0] !== value) {
+ t1 = () => {
+ setLocalValue(value);
+ document.title = `Value: ${value}`;
+ };
+ t2 = [value];
+ $[0] = value;
+ $[1] = t1;
+ $[2] = t2;
+ } else {
+ t1 = $[1];
+ t2 = $[2];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[3] !== localValue) {
+ t3 = {localValue}
;
+ $[3] = localValue;
+ $[4] = t3;
+ } else {
+ t3 = $[4];
+ }
+ return t3;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ value: "test" }],
+};
+
+```
+
+### Eval output
+(kind: exception) useState is not defined
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.js
new file mode 100644
index 0000000000..11c4340eab
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/derived-state-from-prop-with-side-effect.js
@@ -0,0 +1,17 @@
+// @validateNoDerivedComputationsInEffects
+
+function Component({value}) {
+ const [localValue, setLocalValue] = useState('');
+
+ useEffect(() => {
+ setLocalValue(value);
+ document.title = `Value: ${value}`;
+ }, [value]);
+
+ return {localValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{value: 'test'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.expect.md
new file mode 100644
index 0000000000..36aa1ce15d
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.expect.md
@@ -0,0 +1,86 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+
+ function localFunction() {
+ console.log('local function');
+ }
+
+ useEffect(() => {
+ setValue(propValue);
+ localFunction();
+ }, [propValue]);
+
+ return {value}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+function Component(t0) {
+ const $ = _c(6);
+ const { propValue } = t0;
+ const [value, setValue] = useState(null);
+ let t1;
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
+ t1 = function localFunction() {
+ console.log("local function");
+ };
+ $[0] = t1;
+ } else {
+ t1 = $[0];
+ }
+ const localFunction = t1;
+ let t2;
+ let t3;
+ if ($[1] !== propValue) {
+ t2 = () => {
+ setValue(propValue);
+ localFunction();
+ };
+ t3 = [propValue];
+ $[1] = propValue;
+ $[2] = t2;
+ $[3] = t3;
+ } else {
+ t2 = $[2];
+ t3 = $[3];
+ }
+ useEffect(t2, t3);
+ let t4;
+ if ($[4] !== value) {
+ t4 = {value}
;
+ $[4] = value;
+ $[5] = t4;
+ } else {
+ t4 = $[5];
+ }
+ return t4;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ propValue: "test" }],
+};
+
+```
+
+### Eval output
+(kind: ok) test
+logs: ['local function']
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.js
new file mode 100644
index 0000000000..00e658d896
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/effect-contains-local-function-call.js
@@ -0,0 +1,22 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+
+ function localFunction() {
+ console.log('local function');
+ }
+
+ useEffect(() => {
+ setValue(propValue);
+ localFunction();
+ }, [propValue]);
+
+ return {value}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.expect.md
new file mode 100644
index 0000000000..44ca7ffa5a
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.expect.md
@@ -0,0 +1,49 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({initialName}) {
+ const [name, setName] = useState('');
+
+ useEffect(() => {
+ setName(initialName);
+ }, [initialName]);
+
+ return (
+
+ // 🟡 If the is also called outside of the effect, it's still wrong but
+ // should be solved by hoisting state
+ setName(e.target.value)} />
+
+ );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{initialName: 'John'}],
+};
+
+```
+
+
+## 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.derived-state-from-prop-setter-call-outside-effect-no-error.ts:8:4
+ 6 |
+ 7 | useEffect(() => {
+> 8 | setName(initialName);
+ | ^^^^^^^ 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)
+ 9 | }, [initialName]);
+ 10 |
+ 11 | return (
+```
+
+
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.js
new file mode 100644
index 0000000000..7b93e3c79d
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-call-outside-effect-no-error.js
@@ -0,0 +1,23 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({initialName}) {
+ const [name, setName] = useState('');
+
+ useEffect(() => {
+ setName(initialName);
+ }, [initialName]);
+
+ return (
+
+ // 🟡 If the is also called outside of the effect, it's still wrong but
+ // should be solved by hoisting state
+ setName(e.target.value)} />
+
+ );
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{initialName: 'John'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.expect.md
new file mode 100644
index 0000000000..a271a4c54b
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.expect.md
@@ -0,0 +1,46 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function MockComponent({onSet}) {
+ return onSet('clicked')}>Mock Component
;
+}
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+ useEffect(() => {
+ setValue(propValue);
+ }, [propValue]);
+
+ return ;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
+
+```
+
+
+## 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.derived-state-from-prop-setter-used-outside-effect-no-error.ts:11:4
+ 9 | const [value, setValue] = useState(null);
+ 10 | useEffect(() => {
+> 11 | 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)
+ 12 | }, [propValue]);
+ 13 |
+ 14 | return ;
+```
+
+
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.js
new file mode 100644
index 0000000000..ab2c1a5182
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.derived-state-from-prop-setter-used-outside-effect-no-error.js
@@ -0,0 +1,20 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function MockComponent({onSet}) {
+ return onSet('clicked')}>Mock Component
;
+}
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+ useEffect(() => {
+ setValue(propValue);
+ }, [propValue]);
+
+ return ;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.expect.md
new file mode 100644
index 0000000000..90bef0c2e7
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.expect.md
@@ -0,0 +1,43 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+ useEffect(() => {
+ setValue(propValue);
+ globalCall();
+ }, [propValue]);
+
+ return {value}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
+
+```
+
+
+## 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-with-global-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 | globalCall();
+ 9 | }, [propValue]);
+ 10 |
+```
+
+
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.js
new file mode 100644
index 0000000000..6c10927cc1
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/error.effect-with-global-function-call-no-error.js
@@ -0,0 +1,17 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+function Component({propValue}) {
+ const [value, setValue] = useState(null);
+ useEffect(() => {
+ setValue(propValue);
+ globalCall();
+ }, [propValue]);
+
+ return {value}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{propValue: 'test'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.expect.md
new file mode 100644
index 0000000000..b26a51832e
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.expect.md
@@ -0,0 +1,69 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+function Component() {
+ const [firstName, setFirstName] = useState('Taylor');
+ const lastName = 'Swift';
+
+ // 🔴 Avoid: redundant state and unnecessary Effect
+ const [fullName, setFullName] = useState('');
+ useEffect(() => {
+ setFullName(firstName + ' ' + lastName);
+ }, [firstName, lastName]);
+
+ return {fullName}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+function Component() {
+ const $ = _c(5);
+ const [firstName] = useState("Taylor");
+
+ const [fullName, setFullName] = useState("");
+ let t0;
+ let t1;
+ if ($[0] !== firstName) {
+ t0 = () => {
+ setFullName(firstName + " " + "Swift");
+ };
+ t1 = [firstName, "Swift"];
+ $[0] = firstName;
+ $[1] = t0;
+ $[2] = t1;
+ } else {
+ t0 = $[1];
+ t1 = $[2];
+ }
+ useEffect(t0, t1);
+ let t2;
+ if ($[3] !== fullName) {
+ t2 = {fullName}
;
+ $[3] = fullName;
+ $[4] = t2;
+ } else {
+ t2 = $[4];
+ }
+ return t2;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [],
+};
+
+```
+
+### Eval output
+(kind: exception) useState is not defined
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.js
new file mode 100644
index 0000000000..10dba6f999
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-computation-in-effect.js
@@ -0,0 +1,18 @@
+// @validateNoDerivedComputationsInEffects
+function Component() {
+ const [firstName, setFirstName] = useState('Taylor');
+ const lastName = 'Swift';
+
+ // 🔴 Avoid: redundant state and unnecessary Effect
+ const [fullName, setFullName] = useState('');
+ useEffect(() => {
+ setFullName(firstName + ' ' + lastName);
+ }, [firstName, lastName]);
+
+ return {fullName}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.expect.md
new file mode 100644
index 0000000000..c8d60f981b
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.expect.md
@@ -0,0 +1,72 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+export default function Component(props) {
+ const [displayValue, setDisplayValue] = useState('');
+
+ useEffect(() => {
+ const computed = props.prefix + props.value + props.suffix;
+ setDisplayValue(computed);
+ }, [props.prefix, props.value, props.suffix]);
+
+ return {displayValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{prefix: '[', value: 'test', suffix: ']'}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+export default function Component(props) {
+ const $ = _c(7);
+ const [displayValue, setDisplayValue] = useState("");
+ let t0;
+ let t1;
+ if ($[0] !== props.prefix || $[1] !== props.suffix || $[2] !== props.value) {
+ t0 = () => {
+ const computed = props.prefix + props.value + props.suffix;
+ setDisplayValue(computed);
+ };
+ t1 = [props.prefix, props.value, props.suffix];
+ $[0] = props.prefix;
+ $[1] = props.suffix;
+ $[2] = props.value;
+ $[3] = t0;
+ $[4] = t1;
+ } else {
+ t0 = $[3];
+ t1 = $[4];
+ }
+ useEffect(t0, t1);
+ let t2;
+ if ($[5] !== displayValue) {
+ t2 = {displayValue}
;
+ $[5] = displayValue;
+ $[6] = t2;
+ } else {
+ t2 = $[6];
+ }
+ return t2;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ prefix: "[", value: "test", suffix: "]" }],
+};
+
+```
+
+### 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/invalid-derived-state-from-computed-props.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.js
new file mode 100644
index 0000000000..31fb30cef9
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-computed-props.js
@@ -0,0 +1,18 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+export default function Component(props) {
+ const [displayValue, setDisplayValue] = useState('');
+
+ useEffect(() => {
+ const computed = props.prefix + props.value + props.suffix;
+ setDisplayValue(computed);
+ }, [props.prefix, props.value, props.suffix]);
+
+ return {displayValue}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{prefix: '[', value: 'test', suffix: ']'}],
+};
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.expect.md
new file mode 100644
index 0000000000..c06b8772e4
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.expect.md
@@ -0,0 +1,74 @@
+
+## Input
+
+```javascript
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+export default function Component({props}) {
+ const [fullName, setFullName] = useState(
+ props.firstName + ' ' + props.lastName
+ );
+
+ useEffect(() => {
+ setFullName(props.firstName + ' ' + props.lastName);
+ }, [props.firstName, props.lastName]);
+
+ return {fullName}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{props: {firstName: 'John', lastName: 'Doe'}}],
+};
+
+```
+
+## Code
+
+```javascript
+import { c as _c } from "react/compiler-runtime"; // @validateNoDerivedComputationsInEffects
+import { useEffect, useState } from "react";
+
+export default function Component(t0) {
+ const $ = _c(6);
+ const { props } = t0;
+ const [fullName, setFullName] = useState(
+ props.firstName + " " + props.lastName,
+ );
+ let t1;
+ let t2;
+ if ($[0] !== props.firstName || $[1] !== props.lastName) {
+ t1 = () => {
+ setFullName(props.firstName + " " + props.lastName);
+ };
+ t2 = [props.firstName, props.lastName];
+ $[0] = props.firstName;
+ $[1] = props.lastName;
+ $[2] = t1;
+ $[3] = t2;
+ } else {
+ t1 = $[2];
+ t2 = $[3];
+ }
+ useEffect(t1, t2);
+ let t3;
+ if ($[4] !== fullName) {
+ t3 = {fullName}
;
+ $[4] = fullName;
+ $[5] = t3;
+ } else {
+ t3 = $[5];
+ }
+ return t3;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{ props: { firstName: "John", lastName: "Doe" } }],
+};
+
+```
+
+### Eval output
+(kind: ok) John Doe
\ No newline at end of file
diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.js
new file mode 100644
index 0000000000..2df3df1d52
--- /dev/null
+++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/effect-derived-computations/invalid-derived-state-from-destructured-props.js
@@ -0,0 +1,19 @@
+// @validateNoDerivedComputationsInEffects
+import {useEffect, useState} from 'react';
+
+export default function Component({props}) {
+ const [fullName, setFullName] = useState(
+ props.firstName + ' ' + props.lastName
+ );
+
+ useEffect(() => {
+ setFullName(props.firstName + ' ' + props.lastName);
+ }, [props.firstName, props.lastName]);
+
+ return {fullName}
;
+}
+
+export const FIXTURE_ENTRYPOINT = {
+ fn: Component,
+ params: [{props: {firstName: 'John', lastName: 'Doe'}}],
+};