Gracie williams
Gracie williams

Reputation: 1145

Create components with custom refs and access it later

I want to create components dynamically with custom Refs , and I want to use those refs and use with functionalities like measure() etc.

I created following code

var elems = [];
const CarousalLoop = (props) => { 
  
  
  var links = [
    { name: 'america' },
    { name: 'canada' },
    { name: 'norway' },
    { name: 'bahamas' }
  ];
  
   links.forEach((val, index) => {
    elems[val.name]=  useRef(null);
  });
  
 const listItems = links.map((link) =>
 <CustomCarousel ref={elems[link.name]}  category={link.name}/>
    );
    return (
     <View style={{backgroundColor:"white"}}>

       {listItems}
     </View>
    );
}

For example I want to access the compenents using elems["america"] and use it later. but I get following error.

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

Upvotes: 1

Views: 2487

Answers (1)

Drew Reese
Drew Reese

Reputation: 202916

Issues

  1. Yes, React refs need to be forwarded when using functional components.
  2. You can't use the useRef hook within the loop.

Solution

Fix creating the refs. Use a React ref to hold an array of created refs, and pass them by mapped index.

const CarousalLoop = (props) => {

  const linkRefs = useRef([]);
  
  const links = [
    { name: 'america' },
    { name: 'canada' },
    { name: 'norway' },
    { name: 'bahamas' }
  ];

  linkRefs.current = links.map((link) => linkRefs.current[link.name] ?? createRef());
  
  const listItems = links.map((link) => (
    <CustomCarousel
      key={link.name}
      ref={linkRefs.current[link.name]}
      category={link.name}
    />
  ));

  return (
    <View style={{backgroundColor:"white"}}>
      {listItems}
    </View>
  );
}

Forward the ref. This is done by wrapping the CustomCarousel in React.forwardRef.

const CustomCarousel = React.forwardRef((props, ref) => {
  // component logic
  // attach `ref` to DOMNode if necessary or access in `useImperativeHandle` hook
  ...
});

Later when you want/need to access a specific ref, reference it by is key and then access the current value.

linkRefs.current['america']?.current

Upvotes: 1

Related Questions