Динамическое создание ссылок для списка элементов в React с хуками - PullRequest
0 голосов
/ 05 августа 2020

У меня есть компонент, похожий на этот:

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

  ...
}

Я установил плагин ESlint "rules of hooks", и теперь он жалуется, что я использую хуки внутри обратного вызова. Мне нужно «обогатить» каждый элемент в списке ссылкой, а список - динамический c, поэтому я не могу придумать другой способ сделать это?

Предположительно причина в том, что вы не можете гарантировать порядок крючков. Но .map не является функцией asyn c, а сам компонент не имеет побочных эффектов, поэтому я не понимаю, почему я не могу выполнять базовую c итерацию по списку? Любой ввод?

Ответы [ 2 ]

2 голосов
/ 05 августа 2020

Ciao, вы можете попробовать использовать createRef хук, например:

const elementsRef = useRef(results.map(() => createRef()));
0 голосов
/ 05 августа 2020

Возможно, вам подойдет:

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>
...