Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
bd1776b
feat(react): add lifecyclePlugin and useFocusEffect hook
orionmiz Mar 30, 2026
808f841
chore: add changeset for lifecyclePlugin
orionmiz Mar 30, 2026
9ddcbae
Merge branch 'main' into edward_karrot/plugin-refocus
orionmiz Mar 30, 2026
3127294
Merge branch 'main' into edward_karrot/plugin-refocus
orionmiz Mar 31, 2026
a5da496
Merge branch 'main' into edward_karrot/plugin-refocus
orionmiz Apr 1, 2026
a416012
chore(react): deprecate useActiveEffect in favor of useFocusEffect
orionmiz Apr 1, 2026
c20f614
refactor: address review feedback from ENvironmentSet
orionmiz Apr 8, 2026
0ff0341
fix(react): pass --passWithNoTests to jest after lifecycle tests move…
orionmiz Apr 8, 2026
d35d30c
chore(react): remove unused test config and devDependencies
orionmiz Apr 8, 2026
e936a8a
feat(plugin-lifecycle): re-run effect on callback change (React Navig…
orionmiz Apr 8, 2026
bed456f
chore(plugin-lifecycle): add comment explaining render-phase ref write
orionmiz Apr 8, 2026
67f4137
fix(plugin-lifecycle): add reentrancy guard to onChanged
orionmiz Apr 8, 2026
138e32b
test(plugin-lifecycle): add reentrancy test
orionmiz Apr 8, 2026
4f32f6b
test(plugin-lifecycle): fix reentrancy test to use onChanged path
orionmiz Apr 8, 2026
05c219e
test(plugin-lifecycle): use callLog for reentrancy order verification
orionmiz Apr 8, 2026
a81e3eb
fix(plugin-lifecycle): move callbackRef update to useEffect
orionmiz Apr 8, 2026
88b14e1
fix(plugin-lifecycle): use array for pending transitions
orionmiz Apr 8, 2026
95c1da4
Merge branch 'main' into edward_karrot/plugin-refocus
orionmiz Apr 8, 2026
2cd9de5
chore(react): revert esbuild.config.js and tsconfig.json to main
orionmiz Apr 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .changeset/add-lifecycle-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"@stackflow/plugin-lifecycle": minor
---

Add lifecyclePlugin and useFocusEffect hook for activity focus/blur lifecycle

- `useFocusEffect(callback)` hook to register per-activity focus/blur callbacks
- Detection and invocation in plugin `onChanged` (outside React render cycle)
- `callbackRef` pattern for always-latest callback without `useCallback`
- Error isolation via `runSafely()` for all user callbacks
32 changes: 32 additions & 0 deletions .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions extensions/plugin-lifecycle/esbuild.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const { context } = require("esbuild");
const config = require("@stackflow/esbuild-config");
const pkg = require("./package.json");

const watch = process.argv.includes("--watch");
const external = Object.keys({
...pkg.dependencies,
...pkg.peerDependencies,
});

Promise.all([
context({
...config({}),
format: "cjs",
external,
}).then((ctx) =>
watch ? ctx.watch() : ctx.rebuild().then(() => ctx.dispose()),
),
context({
...config({}),
format: "esm",
outExtension: {
".js": ".mjs",
},
external,
}).then((ctx) =>
watch ? ctx.watch() : ctx.rebuild().then(() => ctx.dispose()),
),
]).catch(() => process.exit(1));
71 changes: 71 additions & 0 deletions extensions/plugin-lifecycle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "@stackflow/plugin-lifecycle",
"version": "0.0.1",
"repository": {
"type": "git",
"url": "https://github.com/daangn/stackflow.git",
"directory": "extensions/plugin-lifecycle"
},
"license": "MIT",
"exports": {
".": {
"types": "./dist/index.d.ts",
"require": "./dist/index.js",
"import": "./dist/index.mjs"
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist",
"src",
"README.md"
],
"scripts": {
"build": "yarn build:js && yarn build:dts",
"build:dts": "tsc --emitDeclarationOnly",
"build:js": "node ./esbuild.config.js",
"clean": "rimraf dist",
"dev": "yarn build:js --watch && yarn build:dts --watch",
"test": "yarn jest",
"typecheck": "tsc --noEmit"
},
"jest": {
"testEnvironment": "jsdom",
"coveragePathIgnorePatterns": [
"index.ts"
],
"transform": {
"^.+\\.(t|j)sx?$": "@swc/jest"
}
},
"devDependencies": {
"@stackflow/config": "^1.2.2",
"@stackflow/core": "^1.3.0",
"@stackflow/esbuild-config": "^1.0.3",
"@stackflow/plugin-renderer-basic": "^1.1.13",
"@stackflow/react": "^1.12.0",
"@swc/core": "^1.6.6",
"@swc/jest": "^0.2.36",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.3.2",
"@types/jest": "^29.5.12",
"@types/react": "^18.3.3",
"esbuild": "^0.27.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"rimraf": "^6.1.3",
"typescript": "^5.5.3"
},
"peerDependencies": {
"@stackflow/core": "^1.1.0-canary.0",
"@stackflow/react": "^1.3.2-canary.0",
"react": ">=16.8.0"
},
"publishConfig": {
"access": "public"
}
}
2 changes: 2 additions & 0 deletions extensions/plugin-lifecycle/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { lifecyclePlugin } from "./lifecyclePlugin";
export { useFocusEffect } from "./useFocusEffect";
Loading
Loading