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下类型不匹配就会报错。按以下步骤修改:
- 更新Props接口,添加
containerStyle属性:
interface PopOverProps { label?: string info?: ReactElement | undefined isPopoverOpen?: boolean containerStyle?: React.CSSProperties // 新增样式属性 }
- 传递/定义样式,可以在组件内部设置默认样式,同时支持外部传入自定义样式覆盖:
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:
- 更新Props接口,添加切换回调:
interface PopOverProps { label?: string info?: ReactElement | undefined isPopoverOpen?: boolean containerStyle?: React.CSSProperties onToggle?: (isOpen: boolean) => void // 新增切换回调 }
- 修改组件实现:
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
相关产品推荐
相关产品推荐

