Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Oct 11, 2023
1 parent 4eea5cf commit b500df7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 63 deletions.
37 changes: 11 additions & 26 deletions packages/next/src/client/app-index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { HeadManagerContext } from '../shared/lib/head-manager-context.shared-ru
import {
ActionQueueContext,
GlobalLayoutRouterContext,
type AppRouterActionQueue,
type DispatchStatePromise,
type ActionQueueNode,
} from '../shared/lib/app-router-context.shared-runtime'
import onRecoverableError from './on-recoverable-error'
import { callServer } from './app-call-server'
Expand All @@ -20,7 +23,6 @@ import type {
ReducerActions,
} from './components/router-reducer/router-reducer-types'
import { reducer } from './components/router-reducer/router-reducer'
import type { ReduxDevToolsInstance } from './components/use-flight-router-state'

// Since React doesn't call onerror for errors caught in error boundaries.
const origConsoleError = window.console.error
Expand All @@ -42,25 +44,9 @@ window.addEventListener('error', (ev: WindowEventMap['error']): void => {

const appElement: HTMLElement | Document | null = document

export type AppRouterActionQueue = {
state: AppRouterState | null
devToolsInstance?: ReduxDevToolsInstance
dispatch: any
action: (
state: AppRouterState | null,
action: ReducerActions
) => Promise<AppRouterState | null>
pending: ActionQueueNode | null
}

type ActionQueueNode = {
payload: any
next: ActionQueueNode | null
}

function finishRunningAction(
actionQueue: AppRouterActionQueue,
setState: React.Dispatch<Promise<AppRouterState | null>>
setState: DispatchStatePromise
) {
if (actionQueue.pending !== null) {
actionQueue.pending = actionQueue.pending.next
Expand All @@ -73,7 +59,7 @@ function finishRunningAction(
async function runAction(
actionQueue: AppRouterActionQueue,
payload: ReducerActions,
setState: React.Dispatch<Promise<AppRouterState | null>>
setState: DispatchStatePromise
) {
const prevState = actionQueue.state
const promise = actionQueue.action(prevState, payload)
Expand Down Expand Up @@ -101,20 +87,21 @@ async function runAction(
function dispatchAction(
actionQueue: AppRouterActionQueue,
payload: ReducerActions,
setState: React.Dispatch<Promise<AppRouterState | null>>
setState: DispatchStatePromise
) {
const newAction: ActionQueueNode = {
payload,
next: null,
}
// Check if the queue is empty
// Check if the queue is empty or if the action is a navigation action
if (actionQueue.pending === null || payload.type === 'navigate') {
// The queue is empty, so add the action and start it immediately
// We also immediately start navigations as those shouldn't be blocked
actionQueue.pending = newAction
runAction(actionQueue, newAction.payload, setState)
} else {
// The queue is not empty, so add the action to the end of the queue
// It will be started by finishActions after the previous action finishes
// It will be started by finishRunningAction after the previous action finishes
let last = actionQueue.pending
while (last.next !== null) {
last = last.next
Expand All @@ -125,10 +112,8 @@ function dispatchAction(

let actionQueue: AppRouterActionQueue = {
state: null,
dispatch: (
payload: any,
setState: React.Dispatch<Promise<AppRouterState | null>>
) => dispatchAction(actionQueue, payload, setState),
dispatch: (payload: ReducerActions, setState: DispatchStatePromise) =>
dispatchAction(actionQueue, payload, setState),
action: async (state: AppRouterState | null, action: ReducerActions) => {
if (state === null) throw new Error('Missing state')
const result = reducer(state, action)
Expand Down
3 changes: 2 additions & 1 deletion packages/next/src/client/components/app-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import type {
CacheNode,
AppRouterInstance,
StatePromise,
} from '../../shared/lib/app-router-context.shared-runtime'
import type {
FlightRouterState,
Expand Down Expand Up @@ -84,7 +85,7 @@ function isThenable(value: any): value is Promise<any> {
)
}

function useUnwrapState(state: AppRouterState | Usable<AppRouterState>) {
function useUnwrapState(state: AppRouterState | StatePromise) {
if (isThenable(state)) {
const result = use(state)
return result
Expand Down
36 changes: 6 additions & 30 deletions packages/next/src/client/components/use-flight-router-state.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { Dispatch, Usable } from 'react'
import type { Dispatch } from 'react'
import React, { useContext } from 'react'
import { useRef, useEffect, useCallback } from 'react'
import type {
AppRouterState,
ReducerActions,
ReducerState,
} from './router-reducer/router-reducer-types'
import { ActionQueueContext } from '../../shared/lib/app-router-context.shared-runtime'

Expand Down Expand Up @@ -61,22 +62,6 @@ function normalizeRouterState(val: any): any {
return val
}

// Log router state when actions are triggered.
// function logReducer(fn: typeof reducer) {
// return (
// state: ReducerState<typeof reducer>,
// action: ReducerAction<typeof reducer>
// ) => {
// console.groupCollapsed(action.type)
// console.log('action', action)
// console.log('old', state)
// const res = fn(state, action)
// console.log('new', res)
// console.groupEnd()
// return res
// }
// }

declare global {
interface Window {
__REDUX_DEVTOOLS_EXTENSION__: any
Expand All @@ -90,24 +75,14 @@ export interface ReduxDevToolsInstance {

function useReducerWithReduxDevtoolsNoop(
initialState: AppRouterState
): [
Usable<AppRouterState> | AppRouterState,
Dispatch<ReducerActions>,
() => void
] {
): [ReducerState, Dispatch<ReducerActions>, () => void] {
return [initialState, () => {}, () => {}]
}

function useReducerWithReduxDevtoolsImpl(
initialState: AppRouterState
): [
Usable<AppRouterState> | AppRouterState,
Dispatch<ReducerActions>,
() => void
] {
const [state, setState] = React.useState<
Usable<AppRouterState> | AppRouterState
>(initialState)
): [ReducerState, Dispatch<ReducerActions>, () => void] {
const [state, setState] = React.useState<ReducerState>(initialState)

const actionQueue = useContext(ActionQueueContext)
const devtoolsConnectionRef = useRef<ReduxDevToolsInstance>()
Expand Down Expand Up @@ -148,6 +123,7 @@ function useReducerWithReduxDevtoolsImpl(
const dispatch = useCallback(
(action: ReducerActions) => {
if (!actionQueue) return

if (!actionQueue.state) {
actionQueue.state = initialState
}
Expand Down
23 changes: 17 additions & 6 deletions packages/next/src/shared/lib/app-router-context.shared-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
AppRouterState,
FocusAndScrollRef,
PrefetchKind,
ReducerActions,
ThenableRecord,
} from '../../client/components/router-reducer/router-reducer-types'
import type { FetchServerResponseResult } from '../../client/components/router-reducer/fetch-server-response'
Expand All @@ -12,7 +13,7 @@ import type {
FlightData,
} from '../../server/app-render/types'
import React from 'react'
import type { AppRouterActionQueue } from '../../client/app-index'
import type { ReduxDevToolsInstance } from '../../client/components/use-flight-router-state'

export type ChildSegmentMap = Map<string, CacheNode>

Expand Down Expand Up @@ -138,11 +139,21 @@ if (process.env.NODE_ENV !== 'production') {
TemplateContext.displayName = 'TemplateContext'
}

export let flightRouterState: AppRouterState
export type StatePromise = Promise<AppRouterState>
export type DispatchStatePromise = React.Dispatch<StatePromise>

export const ActionQueueContext =
React.createContext<AppRouterActionQueue | null>(null)
export type AppRouterActionQueue = {
state: AppRouterState | null
devToolsInstance?: ReduxDevToolsInstance
dispatch: (payload: ReducerActions, setState: DispatchStatePromise) => void
action: (state: AppRouterState | null, action: ReducerActions) => StatePromise
pending: ActionQueueNode | null
}

export function updateFlightRouterState(newState: AppRouterState) {
flightRouterState = newState
export type ActionQueueNode = {
payload: any
next: ActionQueueNode | null
}

export const ActionQueueContext =
React.createContext<AppRouterActionQueue | null>(null)

0 comments on commit b500df7

Please sign in to comment.