React use client组件传setShow遇TS71007警告:原因与解决
解决React+TypeScript中
Props must be serializable for components in the "use client" entry file警告 为什么会触发这个警告?
这个警告是Next.js App Router的TypeScript检查规则(错误码TS71007)导致的:
- 标记了
"use client"的组件,Next.js会默认校验其接收的所有props是否可序列化(即能被转换为JSON的类型,比如字符串、数字、普通对象/数组)。 setShow是React的状态更新函数(类型为Dispatch<SetStateAction<boolean>>),属于不可序列化的值(函数无法被JSON序列化),因此触发了这个校验警告。
setShow作为Prop名有问题吗?
完全没有问题。警告里提到"setShow"只是因为它是你传递的那个不可序列化prop的名称,和命名本身无关——哪怕你改成updateVisible、toggleModal这类名字,只要传递的是状态更新函数或其他不可序列化值,都会触发同样的警告。
如何消除警告?
根据你的组件结构,有几种可行方案:
1. 显式声明Props类型并忽略特定规则
如果子组件确实需要接收状态更新函数,可以先明确组件的Props类型,然后在传递props的位置或组件定义处忽略Next.js的不可序列化props检查:
// 子组件(use client) 'use client'; import { Dispatch, SetStateAction } from 'react'; interface ChildProps { setShow: Dispatch<SetStateAction<boolean>>; } export default function Child({ setShow }: ChildProps) { return <button onClick={() => setShow(false)}>关闭</button>; }
在父组件传递props时添加忽略注释:
// 父组件 import Child from './Child'; import { useState } from 'react'; export default function Parent() { const [show, setShow] = useState(true); // eslint-disable-next-line @next/next/no-unserializable-props return <Child setShow={setShow} />; }
2. 将状态逻辑移到客户端组件内部
如果子组件是独立的客户端组件,可以把show的状态直接放在子组件里,避免从父组件传递更新函数:
// 子组件(use client) 'use client'; import { useState } from 'react'; export default function Child() { const [show, setShow] = useState(true); return show ? <button onClick={() => setShow(false)}>关闭</button> : null; }
3. 将父组件标记为"use client"(若父组件是服务器组件)
如果父组件是未标记"use client"的服务器组件,它本身不能传递不可序列化的props(比如函数)给客户端组件。这种情况下,给父组件添加"use client"标记,让它成为客户端组件,就可以正常传递状态更新函数了:
// 父组件(改为客户端组件) 'use client'; import Child from './Child'; import { useState } from 'react'; export default function Parent() { const [show, setShow] = useState(true); return <Child setShow={setShow} />; }
4. 使用React Context传递状态更新逻辑
如果需要在多个组件间共享状态更新函数,可以用Context封装状态逻辑,避免直接传递函数props:
// 定义Context(use client) 'use client'; import { createContext, useContext, useState, Dispatch, SetStateAction } from 'react'; interface ShowContextType { show: boolean; setShow: Dispatch<SetStateAction<boolean>>; } const ShowContext = createContext<ShowContextType | null>(null); export function ShowProvider({ children }: { children: React.ReactNode }) { const [show, setShow] = useState(true); return <ShowContext.Provider value={{ show, setShow }}>{children}</ShowContext.Provider>; } export function useShow() { const context = useContext(ShowContext); if (!context) throw new Error('useShow must be used within ShowProvider'); return context; }
然后在子组件中使用:
// 子组件(use client) 'use client'; import { useShow } from './ShowContext'; export default function Child() { const { setShow } = useShow(); return <button onClick={() => setShow(false)}>关闭</button>; }
内容的提问来源于stack exchange,提问作者Ali Baghban
相关产品推荐
相关产品推荐

