Open-Source Wikis

/

React

/

How to contribute

/

Development workflow

facebook/react

Development workflow

The day-to-day of working in facebook/react.

Cloning, branching, syncing

The project uses GitHub's standard fork-and-PR model for outside contributors. Maintainers (the names in the MAINTAINERS file) push branches directly to the facebook/react repo.

# First time
git clone https://github.com/<your-fork>/react.git
cd react
git remote add upstream https://github.com/facebook/react.git
yarn install

# Per change
git fetch upstream
git checkout -b my-fix upstream/main
# ... edit, build, test ...
git push origin my-fix

Branch names don't have a strict convention. The team commonly uses <author>/<short-description>, fix-<area>-<issue>, or [area]-<short>.

Commit conventions

The dominant convention is a short subject line with a [scope] prefix. Browse git log --oneline and you'll see:

[Fiber] Double invoke Effects in StrictMode after Fast Refresh (#35962)
[Fizz] add additional task reentrancy protections (#36291)
[compiler] Fix set-state-in-effect false negative ... (#36107)
[DevTools] feat: display subtree for Activity ... (#36094)

Common scope prefixes seen in git log:

  • [Fiber] — reconciler internals
  • [Fizz] — streaming SSR
  • [Flight] — Server Components / RSC payloads
  • [compiler] — the React Compiler
  • [DevTools] — DevTools backend or frontend
  • [react-native-renderer] — Native renderer bridge
  • [eprh]eslint-plugin-react-hooks

This is convention, not enforced. Squash-merging means the PR title becomes the final commit message; many maintainers rewrite the title to match this convention before merging.

Local builds you'll actually run

# Sanity build for a focused area:
yarn build react/index,react-dom/index,react-dom/client,scheduler --type=NODE_DEV

# Devtools-style build (everything devtools needs):
yarn build-for-devtools-dev

# Full release build (slow, but matches CI):
yarn build

Outputs land in build/, partitioned by release channel: build/oss-stable/..., build/oss-experimental/..., build/facebook-www/..., build/facebook-react-native/....

Testing while iterating

# Run a focused subset:
yarn test packages/react-reconciler/src/__tests__/ReactHooks-test.js -t "useState"

# Run everything in the experimental channel (the default):
yarn test

# Pin to a single channel:
yarn test-stable
yarn test-www
yarn test-classic

# Run tests against the built bundles, not the source:
yarn test --build

The --build mode is what catches bundling regressions. CI runs both source and build modes on every PR for the most central packages.

Lint and format

yarn linc          # lint only changed files (fast, used pre-push)
yarn lint          # lint everything
yarn flow          # Flow check the runtime
yarn prettier      # write changed files
yarn prettier-all  # rewrite everything (rare, only after big mechanical changes)

ESLint config: .eslintrc.js. Custom React-internal rules: scripts/eslint-rules/. Flow configs are auto-generated per-renderer by scripts/flow/createFlowConfigs.js (this is what yarn install's postinstall runs).

Release channel choreography

Most non-trivial changes target the experimental channel first:

  1. Land your change behind a feature flag, default-off. CI runs across all channels and your code is dead-code-eliminated everywhere except experimental.
  2. Once you flip the flag in packages/shared/forks/ReactFeatureFlags.js (the experimental fork), the next nightly prerelease publishes a 0.0.0-experimental-<sha>-<date> package.
  3. After bake time, flip in packages/shared/ReactFeatureFlags.js (which controls stable). The next nightly publishes a 0.0.0-<sha>-<date> package on the next channel.
  4. Eventually a stable release is cut from a "next" version using scripts/release/prepare-release-from-npm.js. This is a manual process driven by a release engineer.

The full release script docs are in scripts/release/README.md. The flag layout is in reference/configuration.

Generating error codes

Production builds replace throw new Error('long human message') with throw Error(formatProdErrorMessage(123)), where 123 is an integer code resolved by react.dev/errors. The codes file is scripts/error-codes/codes.json. After adding any new Error thrown by source-level code:

yarn extract-errors
git add scripts/error-codes/codes.json

CI's lint-build step fails if you add a new error message without running this.

Pre-PR checklist

Before opening a PR:

  • yarn lint is clean.
  • yarn flow is clean.
  • yarn test passes for the changed area.
  • If you ran into a new error message: yarn extract-errors.
  • If you added a feature flag: tests cover both branches with @gate.
  • If you changed the published surface of any package, the dangerfile.js bundle-size table will reflect it.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Development workflow – React wiki | Factory