简体   繁体   中英

Dynamically creating Refs for a list of elements in React with hooks

I have a component similar to this:

export function MyListComponent({results}) {
  const resultsWithRefs = results.map(result => {
    ...result,
    ref: useRef(null)
  }

  ...
}

I installed the "rules of hooks" ESlint plugin and it now complains that I am using hooks inside of a callback. I need to "enrich" every element on the list with a ref and the list is dynamic, so I cannot really think of another way to do this?

Supposedly the reason is that you cannot guarantee the order of the hooks. But.map is not an async function and the component itself is without side-effects, so I cannot see why I should not be able to do basic iteration over a list? Any input?

Ciao, you could try to use createRef hook like:

const elementsRef = useRef(results.map(() => createRef()));

Maybe the following can work for you:

 const Input = React.forwardRef((props, ref) => { return <input type="text" ref={ref} />; }); const List = ({ results }) => { const [current, setCurrent] = React.useState(0); //run this before jsx is generated when results change const refs = React.useMemo( () => results.map(() => ({ current: null, })), [results] ); React.useEffect(() => refs[current].current.focus(), [ current, refs, ]); return ( <div> {results.map((r, i) => ( <Input ref={refs[i]} key={r} /> ))} <select onChange={(e) => setCurrent(Number(e.target.value))} > {results.map((r, i) => ( <option value={i} key={r}> {r} </option> ))} </select> </div> ); }; const App = () => { const [results, setResults] = React.useState([1, 2]); return ( <div> <button onClick={() => setResults((r) => [...r, r.length + 1]) } > add result </button> <List results={results} /> </div> ); }; ReactDOM.render(<App />, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM