我想把多次ref传递给子代的子代,但是没有成功。我有一个功能组件,叫做 AvatarBuilder
使用 Avatars
组件。这个组件渲染了一个 Avatar
组成部分。这个想法是为了在 AvatarBuilder
的参考资料 Avatar
组件。
下面是总结的代码片段。
const AvatarBuilder = props => {
...
// in this dummy example i would have 5 avatars
const URLS=[1,2,3,4,5];
const refs = URLS.map(item => ({ ref: React.createRef() }));
return (
<>
<Avatars
ref={refs}
urlList={URLS}
/>
</>
);
const Avatars = React.forwardRef((props, ref) => {
let urlList = props.urlList.map((url, index) => {
return (
<Avatar
ref={ref[index].ref}
url={url}
/>
)
})
return (
<ul className="Avatars" >
{urlList}
</ul>
)
});
const Avatar = React.forwardRef((props, ref) => {
return (
<li className="Avatar">
<img
src={props.url}
ref={ref}
/>
</li>
)
});
我得到以下警告,当所有组件被挂载时,refs数组没有更新。
index.js:1 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of `ForwardRef`.
in h (at Avatar.js:11)
in li (at Avatar.js:10)
in ForwardRef (at Avatars.js:10)
in ul (at Avatars.js:24)
in ForwardRef (at AvatarBuilder.js:189)
in AvatarBuilder (at App.js:19)
in div (at App.js:14)
in App (at src/index.js:9)
in StrictMode (at src/index.js:8)
有什么办法可以解决这个问题吗? 谢谢!我试图通过多次refs数组来解决这个问题。
对于一个功能组件,你必须使用Ref,而不是React.createRef,因为在渲染中会创建一个新的refs实例。
如果你使用React.createRef,那么就使用useMemo来记忆refs。
const AvatarBuilder = props => {
// in this dummy example i would have 5 avatars
const URLS=[1,2,3,4,5];
const refs = React.useMemo(() =>URLS.map(item => ({ ref: React.createRef() })), []); // create refs only once
React.useEffect(() => {
console.log(refs);
},[])
return (
<Avatars
ref={refs}
urlList={URLS}
/>
);
}
const Avatars = React.forwardRef((props, ref) => {
let urlList = props.urlList.map((url, index) => {
return (
<Avatar
ref={ref[index].ref}
url={url}
/>
)
})
return (
<ul className="Avatars" >
{urlList}
</ul>
)
});
const Avatar = React.forwardRef((props, ref) => {
return (
<li className="Avatar">
<img
src={props.url}
ref={ref}
/>
</li>
)
});
ReactDOM.render(<AvatarBuilder/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app"/>
试试这个。
const AvatarBuilder = props => {
...
// in this dummy example i would have 5 avatars
const URLS=[1,2,3,4,5];
const refs = URLS.map(item => React.createRef());
return (
<>
<Avatars
refs={refs}
urlList={URLS}
/>
</>
);
// you don't need to make it with `fowardRef()`
const Avatars = (props) => {
const {refs} = props;
let urlList = props.urlList.map((url, index) => {
console.log(url, index, typeof (index), ref);
return (
<Avatar
ref={refs[index]}
url={url}
/>
)
})
return (
<ul className="Avatars" >
{urlList}
</ul>
)
};
const Avatar = React.forwardRef((props, ref) => {
return (
<li className="Avatar">
<img
src={props.url}
ref={ref}
/>
</li>
)
});