React 表格​​重新渲染,在表格单元格中输入文本时失去焦点

Posted

技术标签:

【中文标题】React 表格​​重新渲染,在表格单元格中输入文本时失去焦点【英文标题】:React table re-renders, losing focus when input text in table cell 【发布时间】:2021-03-19 22:16:30 【问题描述】:

我有一个反应表如下:

我在下面显示的每个选项卡(EN、CN、VN、TH)中都有一个表格。目前,当我尝试在“消息”列(下表中的第 3 列)中输入文本时,每次输入字母表时都会重新呈现表格。光标将失去焦点,我必须再次手动单击输入框才能继续输入。

table.js

const [playerNotification, setPlayerNotification] = React.useState([
       
            'language': 'vn',
            'notificationDetails': [
                
                    'key': 'event',
                    'description': 'test event',
                    'message': ''
                ,
                
                    'key': 'event 2',
                    'description': 'test event 2',
                    'message': ''
                ,
                
                    'key': 'event 3',
                    'description': 'test event 3',
                    'message': ''
                
            ]
        ,
        
            'language': 'cn',
            'notificationDetails': [
                
                    'key': 'event',
                    'description': 'test event',
                    'message': ''
                ,
                
                    'key': 'event 2',
                    'description': 'test event 2',
                    'message': ''
                ,
                
                    'key': 'event 3',
                    'description': 'test event 3',
                    'message': ''
                
            ]
        ];

const updateMessage = (e, value, index, notificationDetailsIndex) => 

        let copyData =  playerNotification.slice();
        let copy = copyData[index];
        let copyDetails = copy.notificationDetails[notificationDetailsIndex];
        copyDetails.message = value;

        copy.notificationDetails[notificationDetailsIndex] = copyDetails;
        copyData[index] = copy;
        
        setPlayerNotification(copyData);

这是我的表格代码:

<div className=classes.tabsRoot>
      <AppBar position="static" color="default">
        <Tabs
          value=value
          onChange=handleChange
          indicatorColor="primary"
          textColor="primary"
          variant="scrollable"
          scrollButtons="auto"
          aria-label="scrollable auto tabs example"
        >
          <Tab label="EN" ...a11yProps(0) />
          <Tab label="CN" ...a11yProps(1) />
          <Tab label="VN" ...a11yProps(2) />
          <Tab label="TH" ...a11yProps(3) />
        </Tabs>
      </AppBar>
      playerNotification.map((p, index) => 
        return (
          <TabPanel value=value index=index>
            <Table key=index aria-label="simple table">
              <TableHead style=customColumnStyle className=classes.header>
                <TableRow key="header" + p.language>
                  <TableCell className=classes.customBorderRightStyle>
                    Event Trigger Key
                  </TableCell>
                  <TableCell className=classes.customBorderRightStyle>
                    Description
                  </TableCell>
                  <TableCell className=classes.customBorderRightStyle>
                    Messages
                  </TableCell>
                </TableRow>
              </TableHead>
              <TableBody style=customColumnStyle>
                p.notificationDetails.map((notification, notificationIndex) => 
                  return (
                    <Fragment>
                      <TableRow key=p.language + notificationIndex>
                        <TableCell
                          style= backgroundColor: "rgba(0, 0, 0, 0.05)" 
                        >
                          notification.key
                        </TableCell>
                        <TableCell
                          style= backgroundColor: "rgba(0, 0, 0, 0.05)" 
                        >
                          notification.description
                        </TableCell>
                        <TableCell>
                          <input
                            type="text"
                            key=p.language + notification.key + notificationIndex
                            className=classes.customInputStyle
                            onChange=(e) =>
                              updateMessage(
                                e,
                                e.target.value,
                                index,
                                notificationIndex
                              )
                            
                            value=notification.message
                          />
                        </TableCell>
                        /* <TableCell>messageComponent(index, notificationIndex, notification)</TableCell> */
                      </TableRow>
                    </Fragment>
                  );
                )
              </TableBody>
            </Table>
          </TabPanel>
        );
      )
    </div>

我尝试为每个表格行添加一个唯一键,但行为保持不变 - 我的光标不断失去焦点。当我输入字母时,添加自动对焦会使光标跳到第三行。这是我尝试过的链接 React.js - input losing focus when rerendering.

我认为可能的原因可能是因为我每次输入字母时都在循环表格?非常感谢您帮助指出我的表格代码中的问题以及如何解决它。谢谢!

【问题讨论】:

我遇到了类似的问题。你有想过这个吗? 我们更改了设计并改为固定在一张桌子上:P 所以这个问题尚未解决,但如果您设法找到答案,请告诉我谢谢! 我也更改了我的设计,并将 onChange 状态保留在单元格本身中(类似于文档中的示例)。我不相信有一个解决方案可以按照我们最初的计划去做。 【参考方案1】:

只要您对每个可以修改的单元格都有一个唯一的密钥,我就有一个解决方案。

创建一个 useState 变量或 useRef(理想情况下)变量来保存您要保持焦点的单元格的当前键。然后将此变量修改为当前单元格的键以关注 onChange 函数。然后,如果当前单元格键与焦点变量引用匹配,您将有条件地使用 autoFocus 属性:

let editableKeyToFocus = useRef(null);
const key = getUniqueKey();

return (
<TextField
   key=key
   onChange=(e) => 
     editableKeyToFocus.current = key;
     onChangeFunctionToCall()
   
   autoFocus=key === editableKeyToFocus.current
/>

)

换句话说,您将在每次调用 onChange 时手动保留对要保持焦点的单元格的引用。

【讨论】:

以上是关于React 表格​​重新渲染,在表格单元格中输入文本时失去焦点的主要内容,如果未能解决你的问题,请参考以下文章

表格单元格中的多行文本会损坏视图

如何在编辑表格视图单元格中的文本字段时重新加载所有表格视图单元格 - iOS Swift

重新加载单元格中没有图像的表格视图重新加载

文本在表格单元格中重叠自身 SWIFT

如何在表格的一个列单元格中输入字母,而在另一列单元格中只输入数字?

excel表格怎么提取单元格中的部分内容