Это потому, что крючки должны быть c детерминированы в своем порядке. Помещая ловушку вне компонента, react может гарантировать порядок ловушки useImage в каждом рендере.
Если вы поместите его внутри реквизита компонентов, то реакция не может гарантировать порядок; Если порядок в массиве изменится или элементы будут удалены из массива, то перехватчики больше не будут в том же порядке, в каком они были при первоначальном рендеринге.
Подробнее о том, почему они должны быть в порядке, читайте здесь: https://reactjs.org/docs/hooks-rules.html#explanation
Чтобы решить вашу проблему, вы можете вместо этого sh использовать вызов useImage в компоненте:
const Token = props => {
const [tokenImg] = useImage(props.image);
return (
<Image
image={tokenImg}
/ * snip */
/>
);
}
Затем в .map:
tokens.tokens.map(item => <Token image={item.image}/>)