我有一个类似的组件:
export function MyListComponent({results}) {
const resultsWithRefs = results.map(result => {
...result,
ref: useRef(null)
}
...
}
我安装了";钩子规则";ESlint插件,它现在抱怨我在回调中使用钩子。我需要";"丰富";列表中每个带有ref的元素和列表都是动态的,所以我真的想不出其他方法来做到这一点吗?
据推测,原因是您无法保证钩子的顺序。但是.map不是一个异步函数,组件本身也没有副作用,所以我不明白为什么我不能对列表进行基本迭代?有什么意见吗?
Ciao,您可以尝试使用createRef
挂钩,如:
const elementsRef = useRef(results.map(() => createRef()));
也许以下方法对您有效:
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>