React useRef 在运行 useEffect 以填充初始状态后返回 null

Posted

技术标签:

【中文标题】React useRef 在运行 useEffect 以填充初始状态后返回 null【英文标题】:React useRef returning null after running a useEffect to fill the initial state 【发布时间】:2021-12-13 20:22:23 【问题描述】:

我正在尝试使用 react 的 useRef 将我的自定义组件连接到 ref,以便使用 html2canvas 并将元素呈现到画布上。

const dataLetters = 
  headers: [
    'A',
    'B',
    'C',
    'D',
    'E',
    'F',
    'G'
  ],
  rows: [
    ['A', 'B', 'C', 'D', 'E', 'F', 'G'],
  ]
;

export default function LettersPage() 
  // refs
  const LettersTableRef = useRef(null);

  useEffect(() => 
    console.log('letter ref');
    console.log(LettersTableRef.current); // same result when logging LettersTableRef
  , [LettersTableRef]);

  return (
    <Page>
      <CustomizedTable ref=LettersTableRef data=dataLetters  />
    </Page>
  );


但是,当我运行此代码时,控制台在记录“letter ref”后会记录 null。 CustomizedTable 只是获取数据并根据信息构建行和标题 - 没有什么比这更有趣了。

我是 React 和 javascript 的新手。我已经读过我可以在 javascript 中给一个元素一个 id - 我不知道如何在反应上下文中做到这一点,并且我试图坚持在 React 中使用 React 而不是普通 js 的做法。

请让我知道我做错了什么!

-----更新为CustomizeTable添加代码----

import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell,  tableCellClasses  from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';

export default function CustomizedTables( data, id ) 
  return (
    <TableContainer>
      <Table>
        <TableHead>
          <TableRow>
            data.headers.map((header) => (
              <TableCell>header</TableCell>
            ))
          </TableRow>
        </TableHead>
        <TableBody>
          data.rows.map((row) => (
            <TableRow>
              row.map((datum) => (
                <TableCell>datum</TableCell>
              ))
            </TableRow>
          ))
        </TableBody>
      </Table>
    </TableContainer>
  );

【问题讨论】:

您是否检查过浏览器的控制台是否有任何警告?你能发布CustomizedTable 组件吗? 浏览器没有返回错误 - 现在发布 CustomizedTable 组件 【参考方案1】:

您应该在浏览器的控制台上再次检查。 refeach child in a list should have a unique key...应该有一些错误

使用refs 是 React 中的高级主题,您基本上可以获得指向对象的指针。这将适用于对类组件或 HTML 元素的引用,但不能直接与功能组件一起使用。为此,您必须使用forwardRef 将您的功能组件包装在里面。

我已在此处修复了您的代码:https://codesandbox.io/s/vigorous-dew-u2bm9?file=/src/CustomizedTable.jsx

使用forwardRef,您可以设置对任何子元素的引用,以便外部组件可以使用useRef 直接访问它。还有一些其他方法可以获取方法作为参考 useImperativeHandle 但这会更高级。

const CustomizedTables = forwardRef(( data, id , ref) => (
    <TableContainer ref=ref>
      ....
    </TableContainer>
));

我强烈推荐这个主题的官方文档:https://reactjs.org/docs/hooks-reference.html

【讨论】:

我现在正在实施 - 感谢您的详细回复。您是否碰巧知道 useRef 作为指针是否像 document.getElementById 一样工作,以便您可以将指针传递到 html2canvas 并生成元素的画布版本? 当在示例中使用时,引用可以被视为与document.getElementById() 相同的 HTML 元素。所以像getBoundingClientRect 这样的任何“本机”方法都是可用的。 以上解决了我的问题。我很抱歉没有更好地了解 useRef - 我是 React 新手。如果我可能会再问一个问题 - 我正在尝试使用 html2canvas,但我检索到了这个错误:Uncaught (in promise) Error: Element is not attach to a Document after html2canvas(ref).then((canvas) =​​> const imgData = canvas.toDataURL('img/png'); );这导致 Uncaught (in promise) Error: Element is not attach to a Document and could not get the stack frames of error: TypeError: r is null 这是 useRef 还是 html2canvas 库的问题? 您可以创建一个画布元素并再次使用useRef,并提供此对html2canvas 选项的引用。

以上是关于React useRef 在运行 useEffect 以填充初始状态后返回 null的主要内容,如果未能解决你的问题,请参考以下文章

试图让我们在数组中使用 React 的 useRef 来获取音频的持续时间

React useRef 将平滑滚动添加到除 Internet Explorer 之外的所有浏览器都支持的 div

useRef 是不是在 React 中存储变量的地址

在 React 中使用 useRef() 触发 CSS 动画

React - UseState,UseRef..In Trouble

React 钩子 useRef() 如何在幕后工作?那个参考到底是啥?