如何在传递给prop后实例化ref



下面的代码将jsx从父级传递给子级;问题是,参考row.descBox是未定义的,可能是由于parent.js中的jsx尚未运行;我应该如何使它指向span元素?

This is Parent.js

import { useEffect, useRef, useState } from "react";
import "./styles.css";
import Child from "./Child";
export default function Parent() {
const taskRefs = useRef([]);
const [cellContent, setCellContent] = useState([]);
useEffect(() => {
const cellContent = [
{
content: (
<>
<h1>
<span
ref={(el) => {
taskRefs.current[0] = el;
}}
>
inside span
</span>
</h1>
</>
),
descBox: taskRefs.current[0]
}
];
setCellContent(cellContent);
}, []);
return <Child cellContent={cellContent} />;
}

This is Child.js

import { useEffect, useState } from "react";
import "./styles.css";
export const Child = ({ cellContent }) => {
return (
<div className="App">
{cellContent.map((row, i) => {
{
console.log(row.descBox);//this is null!
return <div key={i}>{row.content}</div>;
}
})}
</div>
);
};
export default Child;

试着在codesandbox

在存储的jsx中设置ref的回调将不会运行,直到组件安装在DOM中并且在map()中进行日志记录之前发生(您甚至还没有返回它)。您需要登录useEffect才能看到它的设置。我在下面的代码片段中为每个步骤添加了log调用,以说明顺序。

作为旁注,不能将descBox设置为taskRefs.current[0],因为它将被锁定为undefined。你需要给它赋值ref对象taskRefs或者赋值给taskRefs.current的嵌套数组,因为当ref最终被设置时,它们中的任何一个都会被引用更新。

const { useState, useEffect, useRef } = React;
function App() {
const taskRefs = useRef([]);
const [cellContent, setCellContent] = useState([]);
useEffect(() => {
const cellContent = [
{
content: (
<span
ref={(el) => {
console.log("setting ref");
taskRefs.current[0] = el;
}}
>
inside span
</span>
),
descBox: taskRefs
}
];
setCellContent(cellContent);
}, []);
return <Child cellContent={cellContent} />;
}
function Child({ cellContent }) {
useEffect(() => {
if (cellContent.length) {
console.log("inside useEffect. Ref:",cellContent[0].descBox.current[0]);
} else {
console.log('first render.');
}
});
return (
<div className="App">
{cellContent.map((row, i) => {
console.log("inside map. Ref:", row.descBox.current[0]);
return <div key={i}>{row.content}</div>;
})}
</div>
);
};
const container = document.getElementById('root');
const root = ReactDOM.createRoot(container);
root.render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<div id='root'></div>

沙箱

最新更新