Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

module not found/can't resolve @components/fftdata on custom field component

default discord avatar
djkato12 months ago
30

in

src/collections/audio.ts

I have:


import type { CollectionConfig } from "payload"

export const Audios: CollectionConfig = {
    slug: "audios",
    upload: {
        mimeTypes: ["audio/ogg"],
        staticDir: "data/audio"
    },
    fields: [
...
        {
            name: "fft_data",
            type: "json",
            required: true,
            admin: {
                components: {
                    Field: "@components/fftdata#FFTDataComponent"
                }
            }
        }
    ]
}


And my component is:


src/components/fftdata.tsx
"use client"

export const FFTDataComponent: JSONFieldClientComponent = props => {...}

in my

tsconfig.json

I defined

@components

as:


{
    "compilerOptions": {
//...
        "paths": {
            "@/*": [
                "./src/*"
            ],
            "@payload-config": [
                "./src/payload.config.ts"
            ],
            "@components": [
                "./src/components/"
            ]
        },
//...

What am I doing wrong? I run

pnpm generate:importmap

before

pnpm dev

, but get this import issue.

  • default discord avatar
    zed054712 months ago

    Hey

    @247020304507863040



    Two things:


    1. Looks like you're using visual studio code - can you try just ctrl + clicking onto the component path to see if vscode takes you to the right file


    2. Can you share your package.json



    For #1 try in the importmap where it imports the component

  • default discord avatar
    djkato12 months ago

    wrong assumption, I'm using neovim :p


    package.json
    {
        "name": "@nuphory/backend",
        "version": "1.0.0",
        "description": "A blank template to get started with Payload 3.0",
        "license": "MIT",
        "type": "module",
        "exports": {
            ".": {
                "import": "./src/index.ts",
                "types": "./src/index.ts",
                "default": "./src/index.ts"
            }
        },
        "scripts": {
            "build": "cross-env NODE_OPTIONS=--no-deprecation next build",
            "dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
            "devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev",
            "generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
            "generate:types": "cross-env NODE_OPTIONS=--no-deprecation payload generate:types",
            "fmt": "biome format --write",
            "payload": "cross-env NODE_OPTIONS=--no-deprecation payload",
            "start": "cross-env NODE_OPTIONS=--no-deprecation next start"
        },
        "dependencies": {
            "@euterpe.js/visualizer": "^1.1.1",
            "@payloadcms/db-sqlite": "3.33.0",
            "@payloadcms/next": "3.33.0",
            "@payloadcms/payload-cloud": "3.33.0",
            "@payloadcms/richtext-lexical": "3.33.0",
            "cross-env": "^7.0.3",
            "graphql": "^16.8.1",
            "next": "15.3.0",
            "payload": "3.33.0",
            "react": "19.1.0",
            "react-dom": "19.1.0",
            "sharp": "0.32.6"
        },
        "devDependencies": {
            "@eslint/eslintrc": "^3.2.0",
            "@types/node": "^22.5.4",
            "@types/react": "19.1.0",
            "@types/react-dom": "19.1.2",
            "eslint": "^9.16.0",
            "eslint-config-next": "15.3.0",
            "prettier": "^3.4.2",
            "typescript": "5.7.3"
        },
    }


    I don't think I can go to definition on import path, so I'll try to import it manually and assign it



    import type { CollectionConfig } from "payload"
    import { FFTDataComponent } from "@/components/fftdata"
    
    export const Audios: CollectionConfig = {
    //...
        fields: [
    //...
            {
                name: "fft_data",
                type: "json",
                required: true,
                admin: {
                    components: {
                        Field: FFTDataComponent,
                    }
                }
            }
        ]
    }

    this creates error:


    ts: Type 'JSONFieldClientComponent' is not assignable to type '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined'.
      Type 'ComponentClass<JSONFieldBaseClientProps & { readonly field: Omit<JSONFieldClient, "type"> & Partial<Pick<JSONFieldClient, "type">>; } & Omit<...>, any>' is not assignable to type '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined'.
    
    TypeScript Error Translation(s):
      • I was expecting a type matching '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined', but instead you passed 'JSONFieldClientComponent'.
      • I was expecting a type matching '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined', but instead you passed 'ComponentClass<JSONFieldBaseClientProps & { readonly field: Omit<JSONFieldClient, "type"> & Partial<Pick<JSONFieldClient, "type">>; } & Omit<...>, any>'.
     [2322]


    so prolly not meant to be used this way

  • default discord avatar
    zed054712 months ago
    {
                name: "fft_data",
                type: "json",
                required: true,
                admin: {
                    components: {
                        Field: FFTDataComponent,
                    }
                }
            }

    This is wrong



    Should be a path to the component from the root



    Try without using

    @

    {
        name: "fft_data",
        type: "json",
        required: true,
        admin: {
            components: {
                Field: "/components/fftdata#FFTDataComponent"
            }
        }
    }


    By root I mean wherever your payload.config.ts is

  • default discord avatar
    djkato12 months ago

    ahaa I got it to import I think





    not sure what this means but it seems to have imported with

    Field: "src/components/fftdata#FFTDataComponent"
  • default discord avatar
    zed054712 months ago

    Ok, nice, clear your importmap and regenerate it



    Might be a good idea to delete .next folder



    Also, you are calling useField but you haven't installed

    @payloadcms/ui
  • default discord avatar
    djkato12 months ago

    okay deleted .next, pnpm i

    @967091941873426493

    /ui (lsp didn't complain it's not there and knew the types, weird), epmtied importMap.js, pnpm generate:importmap, pnpm dev aaand



    still



  • default discord avatar
    zed054712 months ago

    It knew the types and didn't complain probably because the export is threaded through the

    payload

    package I think



    Did you install

    ui

    version 3.33.0 to match the rest of your payload versions?



    Payload deps need to be on the same version

  • default discord avatar
    djkato12 months ago

    pnpm seems to have done that for me, but forced it manually just in case. Still doesn't work

  • default discord avatar
    zed054712 months ago

    Can you share the component code



    useField

    is imported through

    @payloadcms/ui

    so it definitely should've complained

  • default discord avatar
    djkato12 months ago

    sure, but I'll cut some fat cuz it's a bit large

  • default discord avatar
    zed054712 months ago

    I need to see imports

  • default discord avatar
    djkato12 months ago
    "use client"
    
    import { AudioVisualBuilder, ShapeType, SmoothingAlgorythm, WaveformOrientation, WaveformShape } from "@euterpe.js/visualizer"
    import { FieldLabel, JSONField, useField } from "@payloadcms/ui"
    import type { JSONFieldClientComponent, JSONFieldLabelClientComponent } from "payload"
    import React, { useRef } from "react"
    import { useEffect } from "react"
    
    export const FFTDataComponent: JSONFieldClientComponent = props => {
        const audio_el = useRef<HTMLAudioElement>(null)
        const canvas_el = useRef<SVGSVGElement>(null)
    
        let duration = 0
        const { value: fft_data, setValue: set_fft_data } = useField<number[]>()
  • default discord avatar
    zed054712 months ago
    const { value: fft_data, setValue: set_fft_data } = useField<number[]>()

    Is missing an arg



    Should be


    const { value: fft_data, setValue: set_fft_data } = useField<number[]>({ path })
  • default discord avatar
    djkato12 months ago
    (alias) useField<number[]>(options?: Options): FieldType<number[]>

    Optional tho?

  • default discord avatar
    zed054712 months ago
    export const FFTDataComponent: JSONFieldClientComponent = props => {
      const audio_el = useRef<HTMLAudioElement>(null)
      const canvas_el = useRef<SVGSVGElement>(null)
    
      let duration = 0
    
      const path = props.path
      const { value: fft_data, setValue: set_fft_data } = useField<number[]>({ path })
      ...
  • default discord avatar
    djkato12 months ago

    path to what



    from props?

  • default discord avatar
    zed054712 months ago

    Path is the path to the field from Payloads perspective



    It gets populated by payload automatically into your component props on the server



    Go ahead and log the props to see what else you get



    You get a bunch of useful stuff, even mroe if the component is an RSC (React Server Component)

  • default discord avatar
    djkato12 months ago

    I did path: props.path



    and I'm now in the admin panel

  • default discord avatar
    zed054712 months ago

    Sounds like progress

  • default discord avatar
    djkato12 months ago

    hid this error, but I guess these things are just my lack of nextjs /react knowledge



    Thanks for the help though!

  • default discord avatar
    zed054712 months ago

    My pleasure!



    We can figure that one out



    Paste your style attribute in here



    I will correct it for you and explain why this is happening, this is a simple runtime error

  • default discord avatar
    djkato12 months ago
    return (
            <div
                style={{
                    display: "flex",
                    "flex-flow": "column nowrap",
                    "justify-content": "space-between",
                    gap: "1rem"
                }}
            >
                <svg ref={canvas_el} viewBox="0 0 500 500" preserveAspectRatio="none" />
                <button
                    type="button"
                    onClick={async () => {
                        // biome-ignore lint/style/noNonNullAssertion: <explanation>
                        // ;[fft_data, duration] = await analyze(audio_el.current!, song_url, fft_data_array)
                        console.log("clicked! Shame you don't know what to do about it :(")
                    }}
                >
                    Create waveform
                </button>
                <input type="text" disabled={true} value={JSON.stringify(fft_data)} />
                {/* biome-ignore lint/a11y/useMediaCaption: <explanation> */}
                <audio />
            </div>
        )
  • default discord avatar
    zed054712 months ago

    In React, we don't use hyphens for attributes and style names. The typing for the

    style

    attribute is

    CSSProperties

    imported from

    'react'
  • default discord avatar
    djkato12 months ago

    display: "flex",


    flexFlow: "column nowrap",


    justifyContent: "space-between",


    gap: "1rem"


    then?

  • default discord avatar
    zed054712 months ago

    This


    <div
      style={{
        display: "flex",
        "flex-flow": "column nowrap",
        "justify-content": "space-between",
        gap: "1rem"
      }}
    >


    Should be:


    <div
      style={{
        display: "flex",
        flexFlow: "column nowrap",
        justifyContent: "space-between",
        gap: "1rem"
      }}
    >


    You got it

  • default discord avatar
    djkato12 months ago

    it's in wohoo

  • default discord avatar
    zed054712 months ago

    If you're more comfortable with CSS/SCSS (Payload uses SCSS for the Admin) you can declare an index.scss in the root of your component and just import it as

    import './index.scss'

    Very nice!



    I love Audio visualizers



    Built a few for my DJ friends back in the day

  • default discord avatar
    djkato12 months ago

    eheheh, I made a whole audio visual library for some client work

  • default discord avatar
    zed054712 months ago

    Via fast fourier transforms



    Oh sweet!



    Let me know if you run into anything else! Glad we got it working here.

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.