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

TypeScript中React-Tiny-Popover组件:样式报错与关闭功能实现问题

TypeScript中react-tiny-popover组件的两个问题解决方法

我正在TypeScript中开发Popover组件,现面临两个问题:一是按照react-tiny-popover文档尝试添加containerStyle时出现报错,不知如何正确设置样式;二是当前仅能打开Popover,需要实现关闭功能。相关代码如下:

import { Popover } from 'react-tiny-popover'
import './popover.scss'
import {ReactElement} from "react";
import {Button} from "../Button/Button";

interface PopOverProps {
    label?:string
    info?:ReactElement | undefined
    isPopoverOpen?:boolean
}

export const PopOver = ({
    label="Info",
    isPopoverOpen=false,
    info=(
      <>
          <p>Hello world!</p>
          <p>Example of how does the long text look here - <em>lorem ipsum</em> <strong>lorem ipsum</strong></p>
      </>
    ),
    ...props
}: PopOverProps) => {
    return (
        <Popover
            isOpen={isPopoverOpen}
            content={info}
        >
            <Button
                label={label}
                size={"small"}
                kind={"outline"}
            />
        </Popover>
    )
}

一、解决containerStyle报错问题

react-tiny-popover的containerStyle要求传入符合React.CSSProperties类型的样式对象,TypeScript下类型不匹配就会报错。按以下步骤修改:

  1. 更新Props接口,添加containerStyle属性:
interface PopOverProps {
    label?: string
    info?: ReactElement | undefined
    isPopoverOpen?: boolean
    containerStyle?: React.CSSProperties // 新增样式属性
}
  1. 传递/定义样式,可以在组件内部设置默认样式,同时支持外部传入自定义样式覆盖:
export const PopOver = ({
    label="Info",
    isPopoverOpen=false,
    info=(
      <>
          <p>Hello world!</p>
          <p>Example of how does the long text look here - <em>lorem ipsum</em> <strong>lorem ipsum</strong></p>
      </>
    ),
    containerStyle,
    ...props
}: PopOverProps) => {
    // 定义默认弹窗容器样式
    const defaultContainerStyle: React.CSSProperties = {
        backgroundColor: '#fff',
        borderRadius: '8px',
        boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
        padding: '16px'
    }

    return (
        <Popover
            isOpen={isPopoverOpen}
            content={info}
            // 合并默认样式和外部传入样式
            containerStyle={{ ...defaultContainerStyle, ...containerStyle }}
        >
            <Button
                label={label}
                size={"small"}
                kind={"outline"}
            />
        </Popover>
    )
}

这样既解决了类型报错,又保留了样式的灵活性。


二、实现Popover关闭功能

目前组件依赖父组件传入的isPopoverOpen控制显示,但没有触发关闭的逻辑,提供两种实现方式:

方式1:组件内部自主管理状态(适合独立使用)

让组件自己维护弹窗的打开/关闭状态,不需要父组件干预:

import { Popover } from 'react-tiny-popover'
import './popover.scss'
import {ReactElement, useState} from "react";
import {Button} from "../Button/Button";

interface PopOverProps {
    label?: string
    info?: ReactElement | undefined
    containerStyle?: React.CSSProperties
}

export const PopOver = ({
    label="Info",
    info=(
      <>
          <p>Hello world!</p>
          <p>Example of how does the long text look here - <em>lorem ipsum</em> <strong>lorem ipsum</strong></p>
      </>
    ),
    containerStyle,
    ...props
}: PopOverProps) => {
    const [isOpen, setIsOpen] = useState(false)
    const defaultContainerStyle: React.CSSProperties = {
        backgroundColor: '#fff',
        borderRadius: '8px',
        boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
        padding: '16px'
    }

    return (
        <Popover
            isOpen={isOpen}
            content={
                <>
                    {info}
                    {/* 可选:在弹窗内添加关闭按钮 */}
                    <button 
                        onClick={() => setIsOpen(false)} 
                        style={{ 
                            marginTop: '12px', 
                            border: 'none', 
                            background: 'none', 
                            color: '#666', 
                            cursor: 'pointer' 
                        }}
                    >
                        关闭
                    </button>
                </>
            }
            containerStyle={{ ...defaultContainerStyle, ...containerStyle }}
            onClickOutside={() => setIsOpen(false)} // 点击弹窗外部自动关闭
        >
            <Button
                label={label}
                size={"small"}
                kind={"outline"}
                onClick={() => setIsOpen(!isOpen)} // 点击按钮切换弹窗状态
            />
        </Popover>
    )
}

方式2:父组件控制状态(适合全局状态管理)

如果需要父组件统一控制弹窗的显示状态,添加回调函数让父组件更新isPopoverOpen:

  1. 更新Props接口,添加切换回调:
interface PopOverProps {
    label?: string
    info?: ReactElement | undefined
    isPopoverOpen?: boolean
    containerStyle?: React.CSSProperties
    onToggle?: (isOpen: boolean) => void // 新增切换回调
}
  1. 修改组件实现:
export const PopOver = ({
    label="Info",
    isPopoverOpen=false,
    info=(
      <>
          <p>Hello world!</p>
          <p>Example of how does the long text look here - <em>lorem ipsum</em> <strong>lorem ipsum</strong></p>
      </>
    ),
    containerStyle,
    onToggle,
    ...props
}: PopOverProps) => {
    const defaultContainerStyle: React.CSSProperties = {
        backgroundColor: '#fff',
        borderRadius: '8px',
        boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
        padding: '16px'
    }

    // 触发父组件的状态更新
    const handleToggle = () => {
        onToggle?.(!isPopoverOpen)
    }

    return (
        <Popover
            isOpen={isPopoverOpen}
            content={info}
            containerStyle={{ ...defaultContainerStyle, ...containerStyle }}
            onClickOutside={() => onToggle?.(false)} // 点击外部通知父组件关闭
        >
            <Button
                label={label}
                size={"small"}
                kind={"outline"}
                onClick={handleToggle} // 点击按钮触发状态切换
            />
        </Popover>
    )
}

父组件使用示例:

import { useState } from 'react'
import { PopOver } from './PopOver'

function ParentComponent() {
    const [isPopoverOpen, setIsPopoverOpen] = useState(false)

    return (
        <div>
            <PopOver
                label="打开弹窗"
                isPopoverOpen={isPopoverOpen}
                onToggle={setIsPopoverOpen}
            />
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 05:06:42