Кодепен не выводит их одновременно. Это же две разных строчки, то есть два отдельных вывода. Просто пауза между ними минимальная, так как в ответ на изменение стейта происходит сразу ререндеринг, и это срабатывает без твоего участия, то есть не приходится кликать кнопку для этого.

У тебя там сейчас отработало все так, как и должно было отработать. Если ты не понимаешь почему так происходит, а главное - пытаешься заставить код выполнять так, как ты этого хочешь, то займись корректировкой своего мышления. Ошибка многих начинающих в том, что они пытаются научиться магии, думая, что программировать - это заставлять машину делать то, что мы хотим. Это неправильно. Научиться программировать - это научиться понимать машину и понимать что произойдет, если сдеть то или иное, и главное - научиться понимать машину, почему происходит так, как происходит, а не так, как мы этого ожидали (то есть научиться фиксить баги в себе, а не в коде).

Сейчас твоя проблема все еще в том, что ты неправильно понимаешь выполнение useState. Пойми: useState всегда именно возвращает, а не устанавливает значение. Ты думаешь так: в первый раз она установит и потом вернет значение из стейта, а потом она будет сразу возвращать из стейта. Это неправильное восприятие. Хотя конечно же по сути именно так и происходит, но все же правильно понимать так: она сразу же вернет или значение из стейта (если оно есть), или значение, переданное по умолчанию (и присвоит это значение стейту, но так, что это не вызывает ререндеринга).

Для того, чтобы это понять, посмотри вот этот код:
var state = undefined; function useState(defaultValue) { if(state === undefined) { state = {}; state.field = defaultValue; } return state.field; } function setState(value) { setTimeout(() => { state.field = value; }, 1000) } console.log("state", state); var count = useState(5); console.log("count 1", count); console.log("state 1", state); var count = useState(7); console.log("count 2", count); console.log("state 2", state); setState(10); console.log("count 3", count); console.log("state 3", state); setTimeout(() => { console.log("count 4", count); count = useState(); console.log("count 4", count); console.log("state 4", state); }, 2000);
Выполни его в консоли браузера и попробуй оценить результат. А результат будет таков:

state undefined count 1 5 state 1 {field: 5} count 2 5 state 2 {field: 5} count 3 5 state 3 {field: 5} # здесь id таймера из setTimeout 109 # Этот результат появится через 2 секунды. count 4 5 count 4 10 state 4 {field: 10}
Обравти внимание, что state = undefined только в первый раз. Затем у нас всегда один и тот же объект стейта, только меняется его свойство.

В setState я прописал вызов через setTimeout, которое и позволяет симитировать работу нативного setState в том плане, что мы не получаем сразу измененного объекта стейта, то есть код далее выполняется все еще со старым значением стейта.
А второй setTimeout с двухсекундной задержкой имитирует повторный ререндеринг, в котором уже новое значение стейта, то есть хотя мы и не вызываем в этом блоке setState, а получаем актуальное значение через useState, мы получаем именно новое значение. При этом я специально здесь сразу два вывода count сделал, чтобы показать тебе, что старая переменная count даже через 2 секунды содержала именно старое значение, после чего мы ей присвоили новое значение.

Вот научись понимать эту логику и то, что код рендерера каждый раз выполняется от и до.