Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate Router State Access #13073

Open
ryanflorence opened this issue Feb 20, 2025 · 0 comments
Open

Consolidate Router State Access #13073

ryanflorence opened this issue Feb 20, 2025 · 0 comments

Comments

@ryanflorence
Copy link
Member

Discussed in #12358

Originally posted by ryanflorence November 23, 2024
Right now you access active, pending, and transitioning states from a bunch of different hooks. This proposal hopes to consolidate them all into a simpler API.

Today

Accessing Current States

let location = useLocation()
let params = useParams()
let [searchParams] = useSearchParams()
let matches = useMatches()
let type = useNavigationType()
<NavLink to={path}>{({ isActive }) => isActive}</NavLink>

Accessing Pending States

let navigation = useNavigation()
navigation.location

// have to construct search params
let searchParams = new URLSearchParams(
  navigation.location.search,
)

// no access
let params = undefined
let type = undefined

// access to form stuff (rarely used, fetchers usually better)
navigation.formAction // etc.
<NavLink to={path}>{({ isPending }) => isPending}</NavLink>

Accessing View Transition States

let state = useViewTransitionState(to)
<NavLink to={path}>
  {({ isTransitioning }) => isTransitioning}
</NavLink>

Proposal: Consolidate into one hook

All of those hooks are either accessing active/pending states or matching against a path and providing active/pending states. We can do this with one hook.

type RouterStateVariant = {
  location: Location
  searchParams: URLSearchParams
  params: Params
  matches: Matches
}

type RouterState = {
  active: RouterStateVariant
  pending: null | RouterStateVariant
  transitioning: boolean
}

let { active, pending, transitioning } = useRouterState()

// user clicks a link, both active and pending could have values
active.location
pending.location

By providing a path to the hook, we can match against it to determine the states, and even provide better types

type RouterStateVariant<Path> = {
  location: Location<Path>
  searchParams: URLSearchParams<Path>
  params: Params<Path>
  matches: Matches<Path>
  type: NavigationType // Pop, Push, Replace
}

type RouterState<Path> = {
  active: null | RouterStateVariant<Path>
  pending: null | RouterStateVariant<Path>
  transitioning: boolean
}

let { active, pending, transitioning } =
  useRouterState('/projects/:id')

// the url is /projects/123
active.params.id
active.location // etc.
pending === null

// the url is /projects, user clicked /projects/123
active === null
pending.params.id
pending.location

Deprecations

This one hook can deprecate all eight of these:

  • useLocation
  • useSearchParams
  • useParams
  • useTransitionState
  • useNavigation
  • useMatches
  • useMatch(pattern)
  • useNavigationType

Refactor

Probably some potential refactoring to simplify the code and have the deprecated hooks (and NavLink) use the new hook underneath.

@ryanflorence ryanflorence moved this to Planned in Roadmap Feb 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Planned
Development

No branches or pull requests

1 participant