Skip to content

Commit

Permalink
Consider dispatch function from useActionState non-reactive (#29917)
Browse files Browse the repository at this point in the history
Updated version of #29758 removing `useFormState` since that was the
previous name for `useActionState`.

---------

Co-authored-by: Hieu Do <hieudn.uh@gmail.com>
  • Loading branch information
josephsavona and hieudo-dev authored Jun 17, 2024
1 parent 107a2f8 commit ddcecbb
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 13 deletions.
13 changes: 13 additions & 0 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Effect, ValueKind, ValueReason } from "./HIR";
import {
BUILTIN_SHAPES,
BuiltInArrayId,
BuiltInUseActionStateId,
BuiltInUseEffectHookId,
BuiltInUseInsertionEffectHookId,
BuiltInUseLayoutEffectHookId,
Expand Down Expand Up @@ -266,6 +267,18 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
returnValueReason: ValueReason.State,
}),
],
[
"useActionState",
addHook(DEFAULT_SHAPES, {
positionalParams: [],
restParam: Effect.Freeze,
returnType: { kind: "Object", shapeId: BuiltInUseActionStateId },
calleeEffect: Effect.Read,
hookKind: "useActionState",
returnValueKind: ValueKind.Frozen,
returnValueReason: ValueReason.State,
}),
],
[
"useReducer",
addHook(DEFAULT_SHAPES, {
Expand Down
16 changes: 16 additions & 0 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/HIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,18 @@ export function isSetStateType(id: Identifier): boolean {
return id.type.kind === "Function" && id.type.shapeId === "BuiltInSetState";
}

export function isUseActionStateType(id: Identifier): boolean {
return (
id.type.kind === "Object" && id.type.shapeId === "BuiltInUseActionState"
);
}

export function isSetActionStateType(id: Identifier): boolean {
return (
id.type.kind === "Function" && id.type.shapeId === "BuiltInSetActionState"
);
}

export function isUseReducerType(id: Identifier): boolean {
return id.type.kind === "Function" && id.type.shapeId === "BuiltInUseReducer";
}
Expand All @@ -1551,6 +1563,10 @@ export function isDispatcherType(id: Identifier): boolean {
return id.type.kind === "Function" && id.type.shapeId === "BuiltInDispatch";
}

export function isStableType(id: Identifier): boolean {
return isSetStateType(id) || isSetActionStateType(id) || isDispatcherType(id);
}

export function isUseEffectHookType(id: Identifier): boolean {
return (
id.type.kind === "Function" && id.type.shapeId === "BuiltInUseEffectHook"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ function addShape(
export type HookKind =
| "useContext"
| "useState"
| "useActionState"
| "useReducer"
| "useRef"
| "useEffect"
Expand Down Expand Up @@ -195,6 +196,8 @@ export const BuiltInJsxId = "BuiltInJsx";
export const BuiltInObjectId = "BuiltInObject";
export const BuiltInUseStateId = "BuiltInUseState";
export const BuiltInSetStateId = "BuiltInSetState";
export const BuiltInUseActionStateId = "BuiltInUseActionState";
export const BuiltInSetActionStateId = "BuiltInSetActionState";
export const BuiltInUseRefId = "BuiltInUseRefId";
export const BuiltInRefValueId = "BuiltInRefValue";
export const BuiltInMixedReadonlyId = "BuiltInMixedReadonly";
Expand Down Expand Up @@ -396,6 +399,25 @@ addObject(BUILTIN_SHAPES, BuiltInUseStateId, [
],
]);

addObject(BUILTIN_SHAPES, BuiltInUseActionStateId, [
["0", { kind: "Poly" }],
[
"1",
addFunction(
BUILTIN_SHAPES,
[],
{
positionalParams: [],
restParam: Effect.Freeze,
returnType: PRIMITIVE_TYPE,
calleeEffect: Effect.Read,
returnValueKind: ValueKind.Primitive,
},
BuiltInSetActionStateId
),
],
]);

addObject(BUILTIN_SHAPES, BuiltInUseReducerId, [
["0", { kind: "Poly" }],
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import {
Place,
computePostDominatorTree,
getHookKind,
isDispatcherType,
isSetStateType,
isStableType,
isUseOperator,
} from "../HIR";
import { PostDominator } from "../HIR/Dominator";
Expand Down Expand Up @@ -220,10 +219,7 @@ export function inferReactivePlaces(fn: HIRFunction): void {

if (hasReactiveInput) {
for (const lvalue of eachInstructionLValue(instruction)) {
if (
isSetStateType(lvalue.identifier) ||
isDispatcherType(lvalue.identifier)
) {
if (isStableType(lvalue.identifier)) {
continue;
}
reactiveIdentifiers.markReactive(lvalue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import {
ReactiveFunction,
ReactiveInstruction,
ReactiveScopeBlock,
isDispatcherType,
isSetStateType,
isStableType,
} from "../HIR";
import { eachPatternOperand } from "../HIR/visitors";
import { collectReactiveIdentifiers } from "./CollectReactiveIdentifiers";
Expand Down Expand Up @@ -57,10 +56,7 @@ class Visitor extends ReactiveFunctionVisitor<ReactiveIdentifiers> {
case "Destructure": {
if (state.has(value.value.identifier.id)) {
for (const lvalue of eachPatternOperand(value.lvalue.pattern)) {
if (
isSetStateType(lvalue.identifier) ||
isDispatcherType(lvalue.identifier)
) {
if (isStableType(lvalue.identifier)) {
continue;
}
state.add(lvalue.identifier.id);
Expand All @@ -75,7 +71,7 @@ class Visitor extends ReactiveFunctionVisitor<ReactiveIdentifiers> {
if (
lvalue !== null &&
state.has(value.object.identifier.id) &&
!isSetStateType(lvalue.identifier)
!isStableType(lvalue.identifier)
) {
state.add(lvalue.identifier.id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@

## Input

```javascript
import { useActionState } from "react";

function Component() {
const [actionState, dispatchAction] = useActionState();
const onSubmitAction = () => {
dispatchAction();
};
return <Foo onSubmitAction={onSubmitAction} />;
}

function Foo() {}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};

```

## Code

```javascript
import { c as _c } from "react/compiler-runtime";
import { useActionState } from "react";

function Component() {
const $ = _c(1);
const [actionState, dispatchAction] = useActionState();
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
const onSubmitAction = () => {
dispatchAction();
};

t0 = <Foo onSubmitAction={onSubmitAction} />;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
}

function Foo() {}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};

```
### Eval output
(kind: ok)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useActionState } from "react";

function Component() {
const [actionState, dispatchAction] = useActionState();
const onSubmitAction = () => {
dispatchAction();
};
return <Foo onSubmitAction={onSubmitAction} />;
}

function Foo() {}

export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [],
};

0 comments on commit ddcecbb

Please sign in to comment.