В чем суть конечного автомата на примере фронтенда?
Конечный автомат это функция.
Смысл конечного автомата (такой функции) в том, что она всегда при одинаковых входящих данных выдает одинаковый результат. Т.е. , например у этой функции есть входящий аргумент с определенным значением. Внутри функции это значение каким либо образом обрабатывается, и эта функция, например, возвращает это обработанное значение. В следующий раз, когда входящий аргумент будет таким же, функция обязательно должна вернуть такое же значение, как и всегда.

В качестве примера можно привести Reducer.
Если есть опыт работы с Redux, то я думаю, поймешь о чем речь.
Если нет, то:
Представь, что в приложении есть некий общий объект, который хранит в себе некие данные этого приложения. Например произошёл запрос на бэкенд, получен ответ, и данные сохранились в этом объекте. К этому объекту есть доступ у всех компонентов приложения. Т.е. отпадает потребность туда сюда из компонента в компонент передавать эти данные в виде props.
Данные в этом объекте может менять определенная функция. И этой функцией является редьюсер. И этот редьюсер и должен быть конечным автоматом.
Т.е. в редьюсер передаются данные, он эти данные принимает, распознает не при помощи if else, а при помощи switch case, так как это удобнее, и меняет данные в объекте. И, в следующий раз при передаче этому редьюсеру этих же данных, он поменяет данные в объекте абсолютно точно также.
const reducer = (state, action) => {
 switch(action.type) {
  case "new value":
  return{...state, value: action.payload}
}
}
Конечный автомат это функция или набор функций которые получает состояние и действие. В зависимости от них что- то делает и задаёт новое состояние. Есть начальное, промежуточные и обычно конечное состояние. Они меняются во время жизненного цикла приложения. Redux хороший пример конечного автомата. Когда мы в вузе это проходили я с удивлением узнал  в нём банальный стейт с функциями в setState.