You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi @V8tr
I'm returning a state on .submitting state for a particular event, but it doesn't return the expected state, here's my code, what am I doing wrong here?
here on .submitting state from an API call I'm calling onSignedIn event, but even after calling return .signedIn(token) , II am not getting this state case let .signedIn(token)
Here's the shortcode
case .submitting:
switch event {
case let .onFailedToLogin(error):
return .error(error)
case let .onSignedIn(token):
return .signedIn(token)
default:
return state
}
Here's the full code
class LoginViewModel: LoginViewModelProtocol, Identifiable {
let authRepository: AuthRepository
@Published var phoneNumber: String = ""
@Published var password: String = ""
@Published var isValid: Bool = false
@Published var phoneNumberError: String?
@Published var passwordError: String?
private var bag = Set<AnyCancellable>()
private let input = PassthroughSubject<Event, Never>()
@Published private(set) var state = State.initial
@Published var phoneNumberValidator = PhoneNumberValidation.empty
@Published var passwordValidator = PasswordValidation.empty
@Inject var router: Router
init() {
authRepository = AuthRepository()
Publishers.system(
initial: state,
reduce: reduce,
scheduler: RunLoop.main,
feedbacks: [
whenSubmitting(),
Self.userInput(input: input.eraseToAnyPublisher())
]
)
.assign(to: \.state, on: self)
.store(in: &bag)
Publishers.CombineLatest(validPhoneNumberPublisher, passwordValidatorPublisher)
.dropFirst()
.sink { _emailError, _passwordValidator in
self.isValid = _emailError.errorMessage == nil &&
_passwordValidator.errorMessage == nil
if self.isValid {
self.send(event: .onSubmitable)
}
print("LoginViewModel combine \(self.state)")
}
.store(in: &bag)
validPhoneNumberPublisher
.dropFirst()
.sink { _error in
self.phoneNumberError = _error.errorMessage
}
.store(in: &bag)
passwordValidatorPublisher
.dropFirst()
.sink { _error in
self.passwordError = _error.errorMessage
}
.store(in: &bag)
}
deinit {
bag.removeAll()
}
func send(event: Event) {
input.send(event)
}
private var validPhoneNumberPublisher: AnyPublisher<PhoneNumberValidation, Never> {
$phoneNumber
.debounce(for: 0.5, scheduler: RunLoop.main)
.removeDuplicates()
.map { _value in
if _value.isEmpty {
return .empty
} else if !_value.isPhoneNumber() {
return .inValidPhoneNumber
} else {
return .validPhoneNumber
}
}
.eraseToAnyPublisher()
}
private var passwordValidatorPublisher: AnyPublisher<PasswordValidation, Never> {
$password
.removeDuplicates()
.debounce(for: 0.5, scheduler: RunLoop.main)
.map { password in
if password.isEmpty {
return .empty
} else {
return passwordStrengthChecker(forPassword: password)
}
}
.eraseToAnyPublisher()
}
}
// MARK: - Inner Types
extension LoginViewModel {
enum State {
case initial
case submitable
case submitting
case signedIn(OauthToken)
case error(HttpError)
}
enum Event {
case onStart
case login
case onSubmitable
case onSignedIn(OauthToken)
case onFailedToLogin(HttpError)
}
}
// MARK: - State Machine
extension LoginViewModel {
private func handleError(error: HttpError) {
switch error {
case let .errors(apiError):
if let errors = apiError.errors {
for error in errors {
if error.key == "invalid_resource_owner_password" {
passwordError = error.message
}
}
}
default:
break
}
}
func reduce(_ state: LoginViewModel.State, _ event: LoginViewModel.Event) -> LoginViewModel.State {
switch state {
case .initial:
switch event {
case .onSubmitable:
return .submitable
default:
return state
}
case .submitting:
switch event {
case let .onFailedToLogin(error):
handleError(error: error)
return .error(error)
case let .onSignedIn(token):
return .signedIn(token)
default:
return state
}
case let .signedIn(token):
return state
case let .error(error):
handleError(error: error)
return state
case .submitable:
switch event {
case .login:
return .submitting
default:
return state
}
}
}
func whenSubmitting() -> Feedback<State, Event> {
Feedback { (state: State) -> AnyPublisher<Event, Never> in
guard case .submitting = state else { return Empty().eraseToAnyPublisher() }
return self.authRepository
.login(phoneNumber: self.phoneNumber, password: self.password)
.map(Event.onSignedIn)
.catch { Just(Event.onFailedToLogin($0)) }
.eraseToAnyPublisher()
}
}
static func userInput(input: AnyPublisher<Event, Never>) -> Feedback<State, Event> {
Feedback { _ in input }
}
}
The text was updated successfully, but these errors were encountered:
Hi @V8tr
I'm returning a state on .submitting state for a particular event, but it doesn't return the expected state, here's my code, what am I doing wrong here?
here on .submitting state from an API call I'm calling onSignedIn event, but even after calling return .signedIn(token) , II am not getting this state case let .signedIn(token)
Here's the shortcode
Here's the full code
The text was updated successfully, but these errors were encountered: