You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TS使用emoji-mart时无法选中表情触发onSelect回调问题

问题原因

回调不触发是三个问题叠加导致的:

  • useEffect依赖项直接写了[props],每次父组件重渲染都会生成新的props对象引用,导致effect反复执行、重复创建Picker实例,旧实例的事件绑定被覆盖,新实例没有正确完成事件挂载。
  • 传给Picker构造函数的ref参数传了React的ref包装对象,而emoji-mart要求这个参数接收真实的DOM节点,导致事件监听根本没有绑定到渲染出来的元素上。
  • ref类型标注错误,容器是普通div元素,标注成HTMLInputElement会导致TS校验出现隐性逻辑问题。
修复方法

修改自定义EmojiPicker组件的逻辑即可,修复后代码如下:

import React, { useEffect, useRef } from "react"
import data from "@emoji-mart/data"
import { Picker, PickerProps } from "emoji-mart"

const EmojiPicker = (props: PickerProps) => {
    // 修正ref类型,同时新增实例存储ref避免重复初始化
    const containerRef = useRef<HTMLDivElement>(null)
    const pickerRef = useRef<Picker | null>(null)

    useEffect(() => {
        // 容器未挂载时不执行初始化
        if (!containerRef.current) return
        // 已经初始化过实例就跳过,避免重复创建
        if (pickerRef.current) return

        // 传入真实DOM节点,而非ref包装对象
        pickerRef.current = new Picker({
            ...props,
            data,
            ref: containerRef.current
        })

        // 组件卸载时清空实例引用,避免内存泄漏
        return () => {
            pickerRef.current = null
        }
    // 移除props依赖,仅在组件首次挂载时初始化一次Picker
    }, [])

    return <div ref={containerRef} />
}

export default EmojiPicker

补充说明:如果需要动态修改Picker配置(比如切换主题、修改回调函数),不要重复创建Picker实例,可通过picker实例暴露的方法单独更新对应属性即可。

内容的提问来源于stack exchange,提问作者Oren Papa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 19:56:49