mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Consider dispatch function from useActionState non-reactive (#29917)
Updated version of #29758 removing `useFormState` since that was the previous name for `useActionState`. --------- Co-authored-by: Hieu Do <hieudn.uh@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import { Effect, ValueKind, ValueReason } from "./HIR";
|
||||
import {
|
||||
BUILTIN_SHAPES,
|
||||
BuiltInArrayId,
|
||||
BuiltInUseActionStateId,
|
||||
BuiltInUseEffectHookId,
|
||||
BuiltInUseInsertionEffectHookId,
|
||||
BuiltInUseLayoutEffectHookId,
|
||||
@@ -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, {
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -118,6 +118,7 @@ function addShape(
|
||||
export type HookKind =
|
||||
| "useContext"
|
||||
| "useState"
|
||||
| "useActionState"
|
||||
| "useReducer"
|
||||
| "useRef"
|
||||
| "useEffect"
|
||||
@@ -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";
|
||||
@@ -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" }],
|
||||
[
|
||||
|
||||
@@ -15,8 +15,7 @@ import {
|
||||
Place,
|
||||
computePostDominatorTree,
|
||||
getHookKind,
|
||||
isDispatcherType,
|
||||
isSetStateType,
|
||||
isStableType,
|
||||
isUseOperator,
|
||||
} from "../HIR";
|
||||
import { PostDominator } from "../HIR/Dominator";
|
||||
@@ -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);
|
||||
|
||||
+3
-7
@@ -10,8 +10,7 @@ import {
|
||||
ReactiveFunction,
|
||||
ReactiveInstruction,
|
||||
ReactiveScopeBlock,
|
||||
isDispatcherType,
|
||||
isSetStateType,
|
||||
isStableType,
|
||||
} from "../HIR";
|
||||
import { eachPatternOperand } from "../HIR/visitors";
|
||||
import { collectReactiveIdentifiers } from "./CollectReactiveIdentifiers";
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+57
@@ -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)
|
||||
+16
@@ -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: [],
|
||||
};
|
||||
Reference in New Issue
Block a user