I have the following code to render a filtered list with animated mounting/unmounting:
function List({ list, templates, transition }) {
return (
<TransitionGroup
className="wscfl-list"
component="ul"
>
{list.map((item) => (
<CSSTransition
key={item.id}
timeout={transition.timeout}
classNames={'wscfl-list__' + item.type + '-'}
>
<li className={'wscfl-list__' + item.type} >
<Item item={item} template={templates[item.type]} pkey={item.id}/>
</li>
</CSSTransition>
))}
</TransitionGroup>
);
}
This will throw an Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Transition which is inside StrictMode. Instead, add a ref directly to the element you want to reference. which I would like to avoid.
I know I'm supposed to the add a ref to the CSSTransition (https://github.com/reactjs/react-transition-group/releases/tag/v4.4.0):
import React from "react"
import { CSSTransition } from "react-transition-group"
const MyComponent = () => {
const nodeRef = React.useRef(null)
return (
<CSSTransition nodeRef={nodeRef} in timeout={200} classNames="fade">
<div ref={nodeRef}>Fade</div>
</CSSTransition>
)
}
However I cannot use useRef inside the map callback since it's not allowed to use hooks in a callback.
I tried to create an array of refs (How target DOM with react useRef in map):
function List({ list, templates, transition }) {
// https://stackoverflow.com/questions/54940399/how-target-dom-with-react-useref-in-map/55105849
const refsArray = [];
for (var i= 0; i < list.length; i++) {
refsArray.push(React.createRef());
}
let refs = React.useRef(refsArray);
React.useEffect(() => {
refs.current[0].current.focus()
}, []);
return (
<TransitionGroup
className="wscfl-list"
component="ul"
>
{list.map((item, i) => (
<CSSTransition
key={item.id}
nodeRef={refs.current[i]}
timeout={transition.timeout}
classNames={'wscfl-list__' + item.type + '-'}
>
<li ref={refs.current[i]} className={'wscfl-list__' + item.type} >
<Item item={item} template={templates[item.type]} pkey={item.id}/>
</li>
</CSSTransition>
))}
</TransitionGroup>
);
}
But this will throw an error on first render TypeError: Cannot read property 'current' of undefined.
9 | }
10 | let refs = React.useRef(refsArray);
11 | React.useEffect(() => {
> 12 | refs.current[0].current.focus()
| ^ 13 | }, []);
14 | return (
15 | <TransitionGroup
Is there any way to use CSSTransition for mapped components without using findDOMNode?
The simplest way to handle this without having the need to use an array of refs is by extracting out the mapped content within another component
const Content = ({item, transition, templates, ...rest}) => {
const nodeRef = React.useRef(null)
return(
<CSSTransition
{...rest}
nodeRef={nodeRef}
timeout={transition.timeout}
classNames={'wscfl-list__' + item.type + '-'}
>
<li ref={nodeRef} className={'wscfl-list__' + item.type} >
<Item item={item} template={templates[item.type]} pkey={item.id}/>
</li>
</CSSTransition>
)
}
function List({ list, templates, transition }) {
return (
<TransitionGroup
className="wscfl-list"
component="ul"
>
{list.map((item) => (
<Content item={item} key={item.id} templates={templates} transition={transition}/>
))}
</TransitionGroup>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With