{"id":22382360,"url":"https://github.com/jcoreio/react-transition-context","last_synced_at":"2025-10-12T21:26:37.880Z","repository":{"id":57346639,"uuid":"181567402","full_name":"jcoreio/react-transition-context","owner":"jcoreio","description":"listen for entering/leaving inside nested transitions","archived":false,"fork":false,"pushed_at":"2024-03-04T16:27:24.000Z","size":1365,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-01T04:42:56.764Z","etag":null,"topics":["nested-transitions","react","transitions"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jcoreio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-04-15T21:19:00.000Z","updated_at":"2023-11-14T01:17:01.000Z","dependencies_parsed_at":"2024-06-19T05:30:34.530Z","dependency_job_id":"e5e5a750-1c94-413e-a423-9801d3cc2d44","html_url":"https://github.com/jcoreio/react-transition-context","commit_stats":{"total_commits":281,"total_committers":4,"mean_commits":70.25,"dds":"0.27402135231316727","last_synced_commit":"80b0179b2d8afb268f17d0781d025a2250bc7670"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/jcoreio/react-transition-context","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcoreio%2Freact-transition-context","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcoreio%2Freact-transition-context/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcoreio%2Freact-transition-context/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcoreio%2Freact-transition-context/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jcoreio","download_url":"https://codeload.github.com/jcoreio/react-transition-context/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcoreio%2Freact-transition-context/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267983365,"owners_count":24176058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nested-transitions","react","transitions"],"created_at":"2024-12-05T00:12:42.158Z","updated_at":"2025-10-12T21:26:32.840Z","avatar_url":"https://github.com/jcoreio.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-transition-context\n\n[![CircleCI](https://circleci.com/gh/jcoreio/react-transition-context.svg?style=svg)](https://circleci.com/gh/jcoreio/react-transition-context)\n[![Coverage Status](https://codecov.io/gh/jcoreio/react-transition-context/branch/master/graph/badge.svg)](https://codecov.io/gh/jcoreio/react-transition-context)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![npm version](https://badge.fury.io/js/react-transition-context.svg)](https://badge.fury.io/js/react-transition-context)\n\nHelps you deal with nested transitions\n\n```\nnpm install --save-dev react-transition-context\n```\n\n# Table of Contents\n\n\u003c!-- toc --\u003e\n\n- [Introduction](#introduction)\n- [`TransitionState` enum](#transitionstate-enum)\n- [Overall transition state](#overall-transition-state)\n  - [Table](#table)\n- [API](#api)\n  - [`TransitionContext` component](#transitioncontext-component)\n  - [`useTransitionContext` hook](#usetransitioncontext-hook)\n  - [`useTransitionStateEffect` hook](#usetransitionstateeffect-hook)\n  - [`useAppearingEffect` hook](#useappearingeffect-hook)\n  - [`useAppearedEffect` hook](#useappearedeffect-hook)\n  - [`useEnteringEffect` hook](#useenteringeffect-hook)\n  - [`useEnteredEffect` hook](#useenteredeffect-hook)\n  - [`useCameInEffect` hook](#usecameineffect-hook)\n  - [`useLeavingEffect` hook](#useleavingeffect-hook)\n  - [`useLeftEffect` hook](#uselefteffect-hook)\n  - [`useAutofocusRef` hook](#useautofocusref-hook)\n\n\u003c!-- tocstop --\u003e\n\n# Introduction\n\nThese days it's fairly easy to animate transitions between your app routes using\nReact components. But it adds difficulty to other things, like focusing an\ninput when a form appears. If the form is part of the initial page load, the\ninput should be focused immediately after mounting. But if you transition to\nthe form from some other route, the input shouldn't be focused until the\ntransition ends. So you need to know if a transition is in progress and take\naction when it ends.\n\nTo make matters worse, there may be nested transitions. For example, in my app,\nI have a fade transition between the `/users` and `/organizations` routes, but\nwithin the `/users` route, I have a drilldown transition from `/users` to\n`/users/:userId`. If the user is in `/organizations/yolo` and clicks a link to\n`/users/jimbo`, there will be a fade transition, but not a drilldown transition.\nSo the `/users/:userId` form needs to know if either the fade or drilldown\ntransition is going before it focuses an input.\n\n`react-transition-context` solves this problem. If the fade and the drilldown\nboth put use it to put their transition state on React context, the\n`/users/:userId` form can register a effect to get called when it's fully\n**in** (rather than mounted but **appearing** or **entering**).\n\n# `TransitionState` enum\n\nThere are five possible values:\n\n- `'appearing'`\n- `'entering'`\n- `'in'`\n- `'leaving'`\n- `'out'`\n\n# Overall transition state\n\nThe _overall transition state_ takes into account both a transition component's\nown transition state, and the overall transition state of its closest ancestor\ntransition component.\n\nFor example:\n\n- If the ancestor is `'in'` and the descendant is `'entering'`, the overall transition state is `'entering'`.\n- If the ancestor is `'leaving'` and the descendant is 'entering', the overall transition state is `'leaving'`.\n- If the ancestor is `'out'` and the descendant is 'leaving', the overall transition state is `'out'`.\n\n## Table\n\n| ↓ Ancestor / Descendant → | `'appearing'` | `'entering'`  | `'in'`        | `'leaving'` | `'out'` |\n| :------------------------ | :------------ | :------------ | :------------ | :---------- | ------- |\n| `'appearing'`             | `'appearing'` | `'appearing'` | `'appearing'` | `'leaving'` | `'out'` |\n| `'entering'`              | `'appearing'` | `'entering'`  | `'entering'`  | `'leaving'` | `'out'` |\n| `'in'`                    | `'appearing'` | `'entering'`  | **`'in'`**    | `'leaving'` | `'out'` |\n| `'leaving'`               | `'leaving'`   | `'leaving'`   | `'leaving'`   | `'leaving'` | `'out'` |\n| `'out'`                   | `'out'`       | `'out'`       | `'out'`       | `'out'`     | `'out'` |\n\n# API\n\n## `TransitionContext` component\n\n```js\nimport { TransitionContext } from 'react-transition-context'\n```\n\n### Props\n\n#### `state: TransitionState` (_optional_)\n\nThe transition state of your transition component that is rendering this.\nOmit this if you just want to consume the [overall transition state](#overall-transition-state) without\nchanging the value for descendants.\n\n#### `children: React.Node` (**required**)\n\nThe content to render\n\n## `useTransitionContext` hook\n\n```js\nimport { useTransitionContext } from 'react-transition-context'\n```\n\nHook that returns the [overall transition state](#overall-transition-state) from\ncontext.\n\n## `useTransitionStateEffect` hook\n\n```js\nimport { useTransitionStateEffect } from 'react-transition-context'\n```\n\n```js\nuseTransitionStateEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes.\n`prevState` will be `null` for the first call (on mount).\n\n## `useAppearingEffect` hook\n\n```js\nimport { useAppearingEffect } from 'react-transition-context'\n```\n\n```js\nuseAppearingEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'out'`/`'leaving'` to `'appearing'`, or is\n`'appearing'` when the component mounts.\n\n## `useAppearedEffect` hook\n\n```js\nimport { useAppearedEffect } from 'react-transition-context'\n```\n\n```js\nuseAppearedEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'appearing'` to `'in'`.\n\n## `useEnteringEffect` hook\n\n```js\nimport { useEnteringEffect } from 'react-transition-context'\n```\n\n```js\nuseEnteringEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'out'`/`'leaving'` to `'entering'`, or is\n`'entering'` when the component mounts.\n\n## `useEnteredEffect` hook\n\n```js\nimport { useEnteredEffect } from 'react-transition-context'\n```\n\n```js\nuseEnteredEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'entering'` to `'in'`.\n\n## `useCameInEffect` hook\n\n```js\nimport { useCameInEffect } from 'react-transition-context'\n```\n\n```js\nuseCameInEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nto `'in'` (from any other state), or is `'in'` when the\ncomponent mounts.\n\n[`useAutofocusRef`](#useautofocusref-hook) is built on\ntop of this.\n\n## `useLeavingEffect` hook\n\n```js\nimport { useLeavingEffect } from 'react-transition-context'\n```\n\n```js\nuseLeavingEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'in'`/`'appearing'`/`'entering'` to `'leaving'`,\nor when the component will unmount and the overall\ntransition state is `'in'`/`'appearing'`/`'entering'`.\n\n## `useLeftEffect` hook\n\n```js\nimport { useLeftEffect } from 'react-transition-context'\n```\n\n```js\nuseLeftEffect(\n  effect: (prevState: ?TransitionState, nextState: TransitionState) =\u003e any\n)\n```\n\nCalls `effect` whenever the [overall transition state](#overall-transition-state) from context changes\nfrom `'leaving'` to `'out'`.\n\n## `useAutofocusRef` hook\n\nCreates a ref you can pass to an element to automatically\nfocus it when the [component comes in](#usecameineffect-hook)\n\n### Example\n\n```js\nimport * as React from 'react'\nimport { useAutofocusRef } from 'react-transition-context'\n\nconst LoginForm = () =\u003e {\n  const autofocusRef = useAutofocusRef()\n  return (\n    \u003cform\u003e\n      \u003cinput type=\"text\" name=\"username\" ref={autofocusRef} /\u003e\n      \u003cinput type=\"password\" name=\"password\" /\u003e\n    \u003c/form\u003e\n  )\n}\n```\n\n## `useTransitionStateEffectFilter`\n\n```js\nimport { useTransitionStateEffectFilter } from 'react-transition-context'\n```\n\n```js\nuseTransitionStateEffectFilter: (\n  filter: (prevState: ?TransitionState, nextState: TransitionState) =\u003e boolean\n) =\u003e (\n  effect: (prevState: ?TransitionState, nextState: TransitionState)\n) =\u003e void\n```\n\nA higher-order function that takes a filter function\nand returns a transition state hook that only calls\n`effect` when the `filter` returns truthy.\n\n(`useTransitionStateEffectFilter` is used to create all\nthe `useAppearingEffect`, `useLeavingEffect`, etc hooks)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcoreio%2Freact-transition-context","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjcoreio%2Freact-transition-context","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcoreio%2Freact-transition-context/lists"}