React搜索框关闭重开后无法输入问题求助
问题原因及解决方案
核心问题
- AnimatePresence 用法错误:你在每个条件分支(
!isSearchOpen和isSearchOpen)里单独嵌套了AnimatePresence,但它需要直接包裹会被挂载/卸载的目标元素,才能正确监听组件进出并触发动画。当前写法会导致组件卸载时的 exit 动画无法被正确捕获,进而引发 DOM 元素状态异常,导致再次打开时输入框无法交互。 - XMarkIcon 多余事件干扰:关闭按钮内的
XMarkIcon绑定了错误的setIsMobOpen事件,会干扰搜索框的关闭逻辑。 - exit 动画的宽度设置问题:关闭时设置
width: 0会直接挤压输入框所在容器,可能导致 DOM 元素尺寸计算异常,再次打开时无法恢复正常交互状态。
修改后的代码
{/* Login and Search Button Start */} <div className="hidden md:block"> <AnimatePresence> {!isSearchOpen ? ( <motion.div key="search-button" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className="md:flex md:items-center md:gap-3" > <button onClick={() => setIsSearchOpen(!isSearchOpen)} className="cursor-pointer flex items-center justify-between gap-2 w-32 px-3 h-8 bg-gray-200 hover:bg-gray-300 border border-solid border-gray-200 rounded-lg" > <span className="text-green-900 font-medium">Search</span> <MagnifyingGlassIcon className="h-5 w-5 text-green-900" /> </button> <LoginButton /> </motion.div> ) : ( <motion.div key="search-input" initial={{ width: 0, opacity: 0 }} animate={{ width: "auto", opacity: 1 }} exit={{ width: 0, opacity: 0 }} className="md:flex md:items-center" > <form> <input placeholder="Search for workshops, articles, and videos" type="text" className="md:w-96 md:px-3 md:mr-3 md:h-7 md:bg-gray-300 md:border-solid md:border-gray-200 md:rounded-lg md:text-sm" /> </form> <button onClick={() => setIsSearchOpen(!isSearchOpen)}> <XMarkIcon className="md:h-7 md:w-7 md:text-green-900 md:cursor-pointer" /> </button> </motion.div> )} </AnimatePresence> </div> {/* Login and Search Button End */}
关键修改点说明
- 统一包裹 AnimatePresence:将
AnimatePresence移到条件渲染外层,确保它能正确监听两个状态元素的挂载/卸载,触发对应动画。 - 添加唯一 key:给两个
motion.div分别设置key="search-button"和key="search-input",让 React 正确识别不同组件实例,避免复用旧 DOM 元素导致状态异常。 - 移除错误事件:删掉
XMarkIcon上的setIsMobOpen事件,确保关闭逻辑只由外层按钮的setIsSearchOpen控制。 - 优化容器对齐:给搜索输入框的
motion.div添加md:items-center,确保输入框和关闭按钮垂直对齐,避免布局偏移。
额外建议
如果关闭时的 width: 0 动画仍然导致输入框异常,可以尝试将 exit 动画改为只使用 opacity,或者给输入框容器添加 overflow: hidden,避免尺寸变化挤压内部元素:
exit={{ opacity: 0, width: 0 }} className="md:flex md:items-center overflow-hidden"
内容的提问来源于stack exchange,提问作者Tri Denda
相关产品推荐
相关产品推荐

