[go: nahoru, domu]

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

Next.js App Router Customer Image Component #549

Open
vader1359 opened this issue Apr 17, 2024 · 1 comment
Open

Next.js App Router Customer Image Component #549

vader1359 opened this issue Apr 17, 2024 · 1 comment

Comments

@vader1359
Copy link
vader1359 commented Apr 17, 2024

CleanShot 2024-04-17 at 09 13 15
I switch to AppRouter and using the "use client" for the NotionPage. The page rendered correctly but no matter what I try, the images are not optimized.
I both tried using the next/image, passing nextImage to the custom component prop
I also create a Cloudinary Image Component and pass to the customer component prop
It does not work.

Anyone have the similar issue?

Test Notion Page: https://www.notion.so/iant1359/About-Us-ea21588ce29b43038e42c7979d715b7d

My code:


// core styles shared by all of react-notion-x (required)
import 'react-notion-x/src/styles.css'

import * as React from 'react'
import dynamic from 'next/dynamic'
import Head from 'next/head'
import Image from 'next/image'
import Link from 'next/link'
// import { useRouter } from 'next/router'

import { ExtendedRecordMap } from 'notion-types'
import { getPageTitle } from 'notion-utils'
import { NotionRenderer } from 'react-notion-x'

import {CldImageProps} from "next-cloudinary"
import CldImage from './CldImage'

// import TweetEmbed from 'react-tweet-embed'

// -----------------------------------------------------------------------------
// dynamic imports for optional components
// -----------------------------------------------------------------------------

const Collection = dynamic(() =>
  import('react-notion-x/build/third-party/collection').then(m => m.Collection),
)

// Extend the props for your ImageComponent
interface ImageComponentProps extends CldImageProps {
  // Add any additional props here if needed
}

const ImageComponent: React.FC<ImageComponentProps> = (props) => (
  <CldImage
    {...props}
    width={2048}
    height={1600}
    alt="illustration image for doc"
    deliveryType="fetch"
    dpr="auto"
    config={{ cloud: { cloudName: 'iant1359' } }}
  />
);

 const NotionPage = ({
  recordMap,
  previewImagesEnabled,
  rootPageId,
  rootDomain,
}: {
  recordMap: ExtendedRecordMap
  previewImagesEnabled?: boolean
  rootPageId?: string
  rootDomain?: string
}) => {
  // const router = useRouter()

  // if (router.isFallback) {
  //   return <Loading />
  // }

  if (!recordMap) {
    return null
  }

  const title = getPageTitle(recordMap)

  // useful for debugging from the dev console
  if (typeof window !== 'undefined') {
    const keys = Object.keys(recordMap?.block || {})
    const block = recordMap?.block?.[keys[0]]?.value
    const g = window as any
    g.recordMap = recordMap
    g.block = block
  }

  const socialDescription = 'React Notion X Demo'
  const socialImage =
    'https://react-notion-x-demo.transitivebullsh.it/social.jpg'

  return (
    <>
      <Head>
        {socialDescription && (
          <>
            <meta name="description" content={socialDescription} />
            <meta property="og:description" content={socialDescription} />
            <meta name="twitter:description" content={socialDescription} />
          </>
        )}

        {socialImage ? (
          <>
            <meta name="twitter:card" content="summary_large_image" />
            <meta name="twitter:image" content={socialImage} />
            <meta property="og:image" content={socialImage} />
          </>
        ) : (
          <meta name="twitter:card" content="summary" />
        )}

        <title>{title}</title>
        <meta property="og:title" content={title} />
        <meta name="twitter:title" content={title} />
        <meta name="twitter:creator" content="@transitive_bs" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <NotionRenderer
        recordMap={recordMap}
        fullPage
        darkMode={false}
        rootDomain={rootDomain}
        rootPageId={rootPageId}
        previewImages={previewImagesEnabled}
        components={{
          // NOTE (transitive-bullshit 3/12/2023): I'm disabling next/image for this repo for now because the amount of traffic started costing me hundreds of dollars a month in Vercel image optimization costs. I'll probably re-enable it in the future if I can find a better solution.
          nextImage: ImageComponent,
          nextLink: Link,
          // Collection,
        }}

        // NOTE: custom images will only take effect if previewImages is true and
        // if the image has a valid preview image defined in recordMap.preview_images[src]
      />
    </>
  )
}

export default NotionPage
import { ExtendedRecordMap, SearchParams, SearchResults } from 'notion-types';

import { previewImagesEnabled } from './config';

// Type definition for the image map (if not already defined)
interface PreviewImageMap {
    [key: string]: string;
}

async function getPreviewImageMap(recordMap: ExtendedRecordMap): Promise<PreviewImageMap> {
    const previewImageMap: PreviewImageMap = {};
    const blocks = recordMap.block;
    
    if (blocks) {
        Object.keys(blocks).forEach(blockId => {
            const block = blocks[blockId].value;
            if (block && block.type === 'image' && block.properties && block.properties.source) {
                const imageUrl = block.properties.source[0][0] as string;  // Assuming source is stored this way
                previewImageMap[blockId] = transformImageURLToPreview(imageUrl);
            }
        });
    }

    return previewImageMap;
}

const notion = new NotionAPI();

export async function getPage(pageId: string): Promise<ExtendedRecordMap> {
    const recordMap = await notion.getPage(pageId);

    if (!recordMap) {
      throw new Error('Failed to retrieve the page data from Notion');
    }

    if (previewImagesEnabled && recordMap) {
      try {
        const previewImageMap = await getPreviewImageMap(recordMap);
        (recordMap as any).preview_images = previewImageMap;
      } catch (error) {
        console.error('Error fetching preview images:', error);
        throw new Error('Error processing preview images');
      }
    }

    console.log(recordMap)

    return recordMap;
}

export async function search(params: SearchParams): Promise<SearchResults> {
    return notion.search(params);
}

function transformImageURLToPreview(url: string): string {
    return url.replace('original', 'preview');
}
@4anghyeon
Copy link

this way worked for me.

function NextImageComponent(props: ImageProps) {
  return (
    <Image
      {...props}
      width={400}
      height={400}
      // loading={"eager"}
    ></Image>
  );
}

function NotionContainer() {
  return (
    <NotionRenderer
      ...
      forceCustomImages={true}
      components={{
        Image: NextImageComponent,
        nextLink: Link,
      }}
    />
  );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants