Первый вариант однозначно лучше, так как родитель теперь не знает про имплементацию детей. Но почему бы вам не инкапсулировать логику внутри Counter в кастомный хук? Он будет использоваться только компонентом Counter, так код будет ещё чище — родитель не знает про имплементацию детей, компонент Counter прост, а внутренняя логика этого компонента описана внутри кастомного хука.
По поводу «сделать лучше»: сделайте две переменных стейта внутри app и передавайте каждому счётчику свои [countN, setCountN] — зачем счётчикам знать про другие счётчики? Тогда внутри счетчика будет меньше кода — нужно обрабатывать данные для конкретно этого счетчика, без необходимости делать setValues({ ...values, })