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】:
您应该在浏览器的控制台上再次检查。 ref
和each 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
在 React 中使用 useRef() 触发 CSS 动画