Repository: facebook/react
File: packages/react-server/src/ReactFizzHooks.js (JavaScript)

Code before:
function useTransition(): [
  boolean,
  (callback: () => void, options?: StartTransitionOptions) => void,
] {
  resolveCurrentlyRenderingComponent();
  return [false, unsupportedStartTransition];
}

function useHostTransitionStatus(): TransitionStatus {
  resolveCurrentlyRenderingComponent();
  return NotPendingTransition;
}

function unsupportedSetOptimisticState() {
  throw new Error('Cannot update optimistic state while rendering.');
}

function useOptimistic<S, A>(
  passthrough: S,
  reducer: ?(S, A) => S,
): [S, (A) => void] {
  resolveCurrentlyRenderingComponent();
  return [passthrough, unsupportedSetOptimisticState];
}

function isSameFormStateInstance(k1: KeyNode, k2: KeyNode): boolean {
  let key1: KeyNode | null = k1;
  let key2: KeyNode | null = k2;
  while (key1 !== null) {
    if (key2 === null) {
      // Key 1 is longer than key 2
      return false;
    }
    if (key1[1] !== key2[1]) {
      // Component name doesn't match
      return false;
    }
    if (key1[2] !== key2[2]) {
      // Key/index doesn't match
      return false;
    }
    key1 = key1[0];
    key2 = key2[0];
  }
  if (key2 !== null) {
    // Key 2 is longer than key 1
    return false;
  }
  // Everything matches
  return true;
}

Review comment (suggestion):
If we accepted a string as the argument to Fizz instead, this could just be `JSON.stringify(key) === formState.key`. That would also allow us to optionally apply a hash to the key.

Code after:
  boolean,
  (callback: () => void, options?: StartTransitionOptions) => void,
] {
  resolveCurrentlyRenderingComponent();
  return [false, unsupportedStartTransition];
}

function useHostTransitionStatus(): TransitionStatus {
  resolveCurrentlyRenderingComponent();
  return NotPendingTransition;
}

function unsupportedSetOptimisticState() {
  throw new Error('Cannot update optimistic state while rendering.');
}

function useOptimistic<S, A>(
  passthrough: S,
  reducer: ?(S, A) => S,
): [S, (A) => void] {
  resolveCurrentlyRenderingComponent();
  return [passthrough, unsupportedSetOptimisticState];
}

function useFormState<S, P>(
  action: (S, P) => Promise<S>,
  initialState: S,
  permalink?: string,
): [S, (P) => void] {
  resolveCurrentlyRenderingComponent();

  // Count the number of useFormState hooks per component. We also use this to
  // track the position of this useFormState hook relative to the other ones in
  // this component, so we can generate a unique key for each one.
  const formStateHookIndex = formStateCounter++;
  const request: Request = (currentlyRenderingRequest: any);

  // Append a node to the key path that represents the form state hook.
  const componentKey: KeyNode | null = (currentlyRenderingKeyPath: any);
  const key: KeyNode = [componentKey, null, formStateHookIndex];
  const keyJSON = JSON.stringify(key);

  // Get the form state. If we received form state from a previous page, then
  // we should reuse that, if the action identity matches. Otherwise we'll use
  // the initial state argument. We emit a comment marker into the stream
  // that indicates whether the state was reused.
  let state;
  const postbackFormState = getFormState(request);
  if (postbackFormState !== null) {
    const postbackKey = postbackFormState[1];
    // TODO: Compare the action identity, too