Skip to content

Commit

Permalink
Revert "(chore): reduce re-render cycles in EndpointContent" (#1272)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Aug 8, 2024
1 parent 3e17743 commit 743bd48
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 103 deletions.
36 changes: 15 additions & 21 deletions packages/ui/app/src/api-page/endpoints/Endpoint.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useAtomValue } from "jotai";
import { memo } from "react";
import { useCallbackOne } from "use-memo-one";
import { FERN_STREAM_ATOM, SLUG_ATOM, useAtomEffect } from "../../atoms";
import { useAtom } from "jotai";
import { memo, useEffect } from "react";
import { FERN_STREAM_ATOM, useResolvedPath } from "../../atoms";
import { useShouldLazyRender } from "../../hooks/useShouldLazyRender";
import { ResolvedEndpointDefinition, ResolvedTypeDefinition } from "../../resolver/types";
import { EndpointContent } from "./EndpointContent";
Expand All @@ -25,25 +24,20 @@ const UnmemoizedEndpoint: React.FC<Endpoint.Props> = ({
isLastInApi,
types,
}) => {
const isStream = useAtomValue(FERN_STREAM_ATOM);
const [isStream, setStream] = useAtom(FERN_STREAM_ATOM);
const resolvedPath = useResolvedPath();

const endpointSlug = endpoint.stream != null && isStream ? endpoint.stream.slug : endpoint.slug;

// TODO: rewrite this with a reducer pattern
useAtomEffect(
useCallbackOne(
(get, set) => {
const selectedSlug = get(SLUG_ATOM);
if (endpoint.stream != null) {
if (endpoint.slug === selectedSlug) {
set(FERN_STREAM_ATOM, false);
} else if (endpoint.stream.slug === selectedSlug) {
set(FERN_STREAM_ATOM, true);
}
}
},
[endpoint.stream, endpoint.slug],
),
);
useEffect(() => {
if (endpoint.stream != null) {
if (endpoint.slug === resolvedPath.slug) {
setStream(false);
} else if (endpoint.stream.slug === resolvedPath.slug) {
setStream(true);
}
}
}, [endpoint.slug, endpoint.stream, resolvedPath.slug, setStream]);

// TODO: this is a temporary fix to only SSG the content that is requested by the requested route.
// - webcrawlers will accurately determine the canonical URL (right now every page "returns" the same full-length content)
Expand Down
98 changes: 76 additions & 22 deletions packages/ui/app/src/api-page/endpoints/EndpointContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,22 @@ import {
store,
useAtomEffect,
} from "../../atoms";
import { ResolvedEndpointDefinition, ResolvedError, ResolvedTypeDefinition } from "../../resolver/types";
import { useSelectedEnvironmentId } from "../../atoms/environment";
import { Breadcrumbs } from "../../components/Breadcrumbs";
import {
ResolvedEndpointDefinition,
ResolvedError,
ResolvedTypeDefinition,
resolveEnvironment,
} from "../../resolver/types";
import { ApiPageDescription } from "../ApiPageDescription";
import { JsonPropertyPath } from "../examples/JsonPropertyPath";
import { CodeExample, generateCodeExamples } from "../examples/code-example";
import { useApiPageCenterElement } from "../useApiPageCenterElement";
import { EndpointContentHeader } from "./EndpointContentHeader";
import { EndpointAvailabilityTag } from "./EndpointAvailabilityTag";
import { EndpointContentLeft, convertNameToAnchorPart } from "./EndpointContentLeft";
import { EndpointStreamingEnabledToggle } from "./EndpointStreamingEnabledToggle";
import { EndpointUrlWithOverflow } from "./EndpointUrlWithOverflow";

const EndpointContentCodeSnippets = dynamic(
() => import("./EndpointContentCodeSnippets").then((mod) => mod.EndpointContentCodeSnippets),
Expand Down Expand Up @@ -71,7 +81,7 @@ const paddingAtom = atom((get) => (get(MOBILE_SIDEBAR_ENABLED_ATOM) ? 0 : 26));

export const EndpointContent = memo<EndpointContent.Props>((props) => {
const { api, showErrors, endpoint: endpointProp, breadcrumbs, hideBottomSeparator = false, types } = props;
const isStream = useAtomValue(FERN_STREAM_ATOM);
const [isStream, setIsStream] = useAtom(FERN_STREAM_ATOM);
const endpoint = isStream && endpointProp.stream != null ? endpointProp.stream : endpointProp;

const ref = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -100,23 +110,21 @@ export const EndpointContent = memo<EndpointContent.Props>((props) => {
const [selectedError, setSelectedError] = useState<ResolvedError | undefined>();

useAtomEffect(
useCallbackOne(
(get) => {
const anchor = get(ANCHOR_ATOM);
const statusCodeOrName = maybeGetErrorStatusCodeOrNameFromAnchor(anchor);
if (statusCodeOrName != null) {
const error = endpoint.errors.find((e) =>
typeof statusCodeOrName === "number"
? e.statusCode === statusCodeOrName
: convertNameToAnchorPart(e.name) === statusCodeOrName,
);
if (error != null) {
setSelectedError(error);
}
useCallbackOne((get) => {
const anchor = get(ANCHOR_ATOM);
const statusCodeOrName = maybeGetErrorStatusCodeOrNameFromAnchor(anchor);
if (statusCodeOrName != null) {
const error = endpoint.errors.find((e) =>
typeof statusCodeOrName === "number"
? e.statusCode === statusCodeOrName
: convertNameToAnchorPart(e.name) === statusCodeOrName,
);
if (error != null) {
setSelectedError(error);
}
},
[setSelectedError],
),
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []),
);

const examples = useMemo(() => {
Expand Down Expand Up @@ -234,8 +242,17 @@ export const EndpointContent = memo<EndpointContent.Props>((props) => {
),
);

// Reset the example height (not in view) if the viewport height changes
useEffect(() => {
if (!isInViewport) {
setExampleHeight(initialExampleHeight);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialExampleHeight]);

const selectedEnvironmentId = useSelectedEnvironmentId();
return (
<section
<div
className={"fern-endpoint-content"}
onClick={() => setSelectedError(undefined)}
ref={ref}
Expand All @@ -246,7 +263,38 @@ export const EndpointContent = memo<EndpointContent.Props>((props) => {
"border-default border-b mb-px pb-12": !hideBottomSeparator,
})}
>
<EndpointContentHeader endpoint={endpointProp} breadcrumbs={breadcrumbs} container={ref} />
<div className="space-y-1 pb-2 pt-8">
<Breadcrumbs breadcrumbs={breadcrumbs} />
<div className="flex items-center justify-between">
<span>
<h1 className="fern-page-heading">
{/* <AnimatedTitle>{endpoint.title}</AnimatedTitle> */}
{endpoint.title}
</h1>
{endpoint.availability != null && (
<span className="inline-block ml-2 align-text-bottom">
<EndpointAvailabilityTag availability={endpoint.availability} minimal={true} />
</span>
)}
</span>

{endpointProp.stream != null && (
<EndpointStreamingEnabledToggle
value={isStream}
setValue={setIsStream}
endpointProp={endpointProp}
container={ref}
/>
)}
</div>
<EndpointUrlWithOverflow
path={endpoint.path}
method={endpoint.method}
selectedEnvironment={resolveEnvironment(endpoint, selectedEnvironmentId)}
showEnvironment
large
/>
</div>
<div className="md:grid md:grid-cols-2 md:gap-8 lg:gap-12">
<div
className="flex min-w-0 max-w-content-width flex-1 flex-col pt-8 md:py-8"
Expand All @@ -255,6 +303,12 @@ export const EndpointContent = memo<EndpointContent.Props>((props) => {
minHeight: `${minHeight}px`,
}}
>
<ApiPageDescription
className="text-base leading-6 mb-12"
description={endpoint.description}
isMarkdown={true}
/>

<EndpointContentLeft
endpoint={endpoint}
showErrors={showErrors}
Expand Down Expand Up @@ -296,7 +350,7 @@ export const EndpointContent = memo<EndpointContent.Props>((props) => {
</aside>
</div>
</div>
</section>
</div>
);
});

Expand Down
52 changes: 0 additions & 52 deletions packages/ui/app/src/api-page/endpoints/EndpointContentHeader.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
dereferenceObjectProperties,
getParameterDescription,
} from "../../resolver/types";
import { ApiPageDescription } from "../ApiPageDescription";
import { JsonPropertyPath } from "../examples/JsonPropertyPath";
import { TypeComponentSeparator } from "../types/TypeComponentSeparator";
import { EndpointError } from "./EndpointError";
Expand Down Expand Up @@ -115,8 +114,7 @@ const UnmemoizedEndpointContentLeft: React.FC<EndpointContentLeft.Props> = ({
}

return (
<div className="flex max-w-full flex-1 flex-col gap-12">
<ApiPageDescription className="text-base leading-6" description={endpoint.description} isMarkdown={true} />
<div className="flex max-w-full flex-1 flex-col gap-12">
{endpoint.pathParameters.length > 0 && (
<EndpointSection title="Path parameters" anchorIdParts={REQUEST_PATH} route={"/" + endpoint.slug}>
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { useAtom, useSetAtom } from "jotai";
import { useSetAtom } from "jotai";
import { MutableRefObject, ReactElement } from "react";
import { FERN_STREAM_ATOM, SLUG_ATOM } from "../../atoms";
import { SLUG_ATOM } from "../../atoms";
import { ResolvedEndpointDefinition } from "../../resolver/types";
import { StreamingEnabledToggle } from "./StreamingEnabledToggle";

export function EndpointStreamingEnabledToggle({
value,
setValue,
endpointProp,
container,
}: {
value: boolean;
setValue: (enabled: boolean) => void;
endpointProp: ResolvedEndpointDefinition;
container: MutableRefObject<HTMLElement | null>;
}): ReactElement {
const [isStream, setIsStream] = useAtom(FERN_STREAM_ATOM);
const setSlug = useSetAtom(SLUG_ATOM);
return (
<StreamingEnabledToggle
className="ml-2 w-[200px]"
value={isStream}
value={value}
setValue={(value) => {
setIsStream(value);
setValue(value);
const endpoint = value && endpointProp.stream != null ? endpointProp.stream : endpointProp;
setSlug(endpoint.slug);
setTimeout(() => {
Expand Down

0 comments on commit 743bd48

Please sign in to comment.