Next.JS ReferenceError 变量未定义

问题描述 投票:0回答:1

在服务器端内部

page.tsx
我有客户端组件
SelectType.tsx
。并且应该像这样工作:

  1. 用户更改选择组件的值
  2. 它会触发内部功能
    page.tsx
  3. 该函数应该更改名为 downloadParams 的对象,但事实并非如此...

这是代码

page.tsx

import {SelectType} from "@/components/SelectType";

export default async function DownloadWithParams ({ params }: { params: { slug: string } }) {

    let downloadParams: DlParameters = {}

    const updateDlParams = async (newParams: DlParameters) => {
        "use server"
        downloadParams = newParams
        console.log(downloadParams)
    }

    return(
        <div className="bg-white w-[80%] min-h-[500px] rounded-2xl shadow-lg p-10 text-zinc-800">
            <div className="parameters-container w-full px-[100px]">
                <form className="flex">
                    <div className="choosetype-container mr-10 grow-[1] flex flex-col">
                        <label className="font-semibold block mb-2">Choose a type:</label>
                        <SelectType dlParams={downloadParams}
                                    updateDlParams={updateDlParams}
                        />
                    </div>
                </form>
            </div>
        </div>
    );
}

SelectType.tsx

'use client'

import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select";
import {DlParameters} from "@/types";

type HandleFnc = (newParams: DlParameters) => void

export function SelectType({dlParams, updateDlParams} : {dlParams : DlParameters, updateDlParams : HandleFnc}) {
    return (
        <Select defaultValue={dlParams?.type || ""}
                onValueChange={async (value: "video" | "audio") => {
                    dlParams.type = value || undefined;
                    await updateDlParams(dlParams);
                }}>
            <SelectTrigger className="grow border-2 border-gray-300 rounded-2xl font-semibold">
                <SelectValue placeholder="Type" />
            </SelectTrigger>
            <SelectContent className="font-semibold" >
                <SelectItem value="video">Video</SelectItem>
                <SelectItem value="audio">Audio</SelectItem>
            </SelectContent>
        </Select>
    );
}

错误信息


Error: downloadParams is not defined

Source
src\app\[slug]\page.tsx (25:9) @ downloadParams

  23 |     const updateDlParams = async (newParams: DlParameters) => {
  24 |         "use server"
> 25 |         downloadParams = newParams
     |         ^
  26 |         console.log(downloadParams)
  27 |     }
  28 |

我只是想了解为什么变量超出了函数的范围以及如何使其工作

javascript reactjs typescript next.js scope
1个回答
0
投票

首先,你不能以这种方式更改变量值,在 React 组件中声明普通变量并尝试更改它们的值是不可能的,但你可以使用 React State hook

useState
创建一个可以通过调用一些事件来更改,例如在您的情况下,您需要包含
"use client"
(选择使用客户端渲染)才能使用反应状态: PS:由于您的
page.tsx
是客户端组件,因此您实际上不需要在
use client
组件中指定
SelectType.tsx
,因为它肯定是客户端组件。

// page.tsx
"use client";
import {SelectType} from "@/components/SelectType";

interface DownloadPageProps {
   params: {
      slug: string
   }
}

export default async function DownloadWithParams ({ params }: DownloadPageProps) {

    const [downloadParams,setDownloadParams] = useState<DlParameters>({})

    // You should not use server action here, this is a very basic use case that does not require server actions at all.
    const updateDlParams = (newParams: DlParameters) => {
        // this will update the state
        setDownloadParams(newParams)
    }

    return(
        <div className="bg-white w-[80%] min-h-[500px] rounded-2xl shadow-lg p-10 text-zinc-800">
            <div className="parameters-container w-full px-[100px]">
                <form className="flex">
                    <div className="choosetype-container mr-10 grow-[1] flex flex-col">
                        <label className="font-semibold block mb-2">Choose a type:</label>
                        <SelectType dlParams={downloadParams}
                                    updateDlParams={updateDlParams}
                        />
                    </div>
                </form>
            </div>
        </div>
    );
}

// SelectType.tsx

/* ...importing modules */

interface SelectTypeProps {
   dlParams : DlParameters, 
   updateDlParams : (newParams: DlParameters) => void
}

export function SelectType({dlParams, updateDlParams} : SelectTypeProps) {
    return (
        <Select defaultValue={dlParams?.type || ""}
                onValueChange={(value: "video" | "audio") => {
                    updateDlParams({ ...dlParams, type: value });
                }}>
            <SelectTrigger className="grow border-2 border-gray-300 rounded-2xl font-semibold">
                <SelectValue placeholder="Type" />
            </SelectTrigger>
            <SelectContent className="font-semibold" >
                <SelectItem value="video">Video</SelectItem>
                <SelectItem value="audio">Audio</SelectItem>
            </SelectContent>
        </Select>
    );
}

PS:如果您不希望整个页面呈现在客户端,您可以为您的表单创建一个包装器(例如

DlParamsForm.tsx
)并在其中包含
"use client"
以及状态逻辑,我强烈推荐这种方法.

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.