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

React结合React-RND与DevExtreme TabPanel时,子组件更新状态引发输入框失焦且文本不更新的问题

React结合React-RND与DevExtreme TabPanel时,子组件更新状态引发输入框失焦且文本不更新的问题

嘿,我之前也碰到过类似的坑!这种输入框失焦+文本不更新的情况,大概率是组件重渲染时DOM被重新创建导致的,咱们一步步来排查解决:

首先排查最常见的问题:不稳定的key值

React靠key来识别组件的身份,如果你的RND元素或者DroppableBox子组件的key用了索引(比如index)或者每次渲染都会变化的值,状态更新后React会直接卸载旧组件、挂载新组件,输入框自然就失焦了。

解决办法:给每个列表项用稳定且唯一的key,比如你数组里每个对象的id字段:

{tabPanelData.map(tab => (
  <TabPanelItem key={tab.id}>
    {tab.contents.map(item => (
      <RND key={item.id} {...rndProps}>
        <DroppableBox item={item} updateTabPanelText={updateTabPanelText} />
      </RND>
    ))}
  </TabPanelItem>
))}

然后优化状态更新函数的稳定性

如果你的updateTabPanelText函数每次父组件渲染都会重新创建,子组件会因为props变化触发不必要的重渲染,也会导致输入框失焦。

用useCallback把这个函数包裹起来,只在依赖项变化时重新生成:

import { useCallback } from 'react';

// 父组件中定义
const updateTabPanelText = useCallback((tabId, itemId, newText) => {
  setTabPanelData(prevData => {
    return prevData.map(tab => {
      if (tab.id !== tabId) return tab;
      return {
        ...tab,
        contents: tab.contents.map(item => 
          item.id === itemId ? {...item, text: newText} : item
        )
      };
    });
  });
}, []); // 这里的依赖项根据实际情况调整,用函数式更新可以减少依赖

让子组件避免不必要的重渲染

给DroppableBox套个memo,这样只有当props真正变化时才会重新渲染:

import { memo } from 'react';

const DroppableBox = memo(({ tabId, updateTabPanelText, item }) => {
  return (
    <input
      type="text"
      value={item.text}
      onChange={(e) => updateTabPanelText(tabId, item.id, e.target.value)}
    />
  );
});

最后检查DevExtreme TabPanel的配置

有些TabPanel会默认卸载未激活的标签页内容,切换回来时重新渲染组件,这也会导致输入框失焦。你可以查下DevExtreme的文档,看看有没有类似keepTabContent或者cacheEnabled这类属性,开启它来保留标签页的DOM结构。

按照这个顺序排查下来,应该就能解决输入框失焦和文本不更新的问题啦!

备注:内容来源于stack exchange,提问作者Faizan Ansari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 14:28:12