mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Repro for unmemoized readonly callback
Repro of a closure that we currently treat as readonly because it captures a possibly-mutable value, but which we later realize is not mutable. Specifically, when we check `exit()` we think `dispatch()` is mutable and therefore consider it captured, which means we can't independently memoize `exit`.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const item = useMutable(props.itemId);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const exit = useCallback(() => {
|
||||
dispatch(createExitAction());
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
|
||||
if (item.value) {
|
||||
exit();
|
||||
}
|
||||
});
|
||||
return () => cleanup.remove();
|
||||
}, [exit, item]);
|
||||
|
||||
maybeMutate(item);
|
||||
|
||||
return <div />;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const $ = React.unstable_useMemoCache(1);
|
||||
const item = useMutable(props.itemId);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const exit = () => {
|
||||
dispatch(createExitAction());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
|
||||
if (item.value) {
|
||||
exit();
|
||||
}
|
||||
});
|
||||
return () => cleanup.remove();
|
||||
}, [exit, item]);
|
||||
|
||||
maybeMutate(item);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <div />;
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
function Component(props) {
|
||||
const item = useMutable(props.itemId);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const exit = useCallback(() => {
|
||||
dispatch(createExitAction());
|
||||
}, [dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const cleanup = GlobalEventEmitter.addListener("onInput", () => {
|
||||
if (item.value) {
|
||||
exit();
|
||||
}
|
||||
});
|
||||
return () => cleanup.remove();
|
||||
}, [exit, item]);
|
||||
|
||||
maybeMutate(item);
|
||||
|
||||
return <div />;
|
||||
}
|
||||
Reference in New Issue
Block a user