Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull to refresh behavior issues #57

Closed
heoblitz opened this issue Sep 25, 2023 · 2 comments · Fixed by #58
Closed

Pull to refresh behavior issues #57

heoblitz opened this issue Sep 25, 2023 · 2 comments · Fixed by #58

Comments

@heoblitz
Copy link
Contributor

heoblitz commented Sep 25, 2023

Hello, first of all, thank you for creating this amazing open-source project.

I encountered a bug with pull to refresh after updating to version 0.6.0.

In some cases, there are states in the store, like token or since, that are unrelated to the view. However, it seems that with the recent commit (865ef58), when the state changes, the Router also updates simultaneously, causing the pull to refresh not to work.

So I was wondering if I could open a PR on TCARouter to allow for setting viewStore isDuplicated closures in the initializer. ( I think that would also allow for optimizations for route updates. )


Simulator.Screen.Recording.-.iPhone.15.Pro.-.2023-09-25.at.13.53.07.mp4

TCACoordinatorPullToRefresh.zip

struct LogInView: View {
  struct ViewState: Equatable {
    let items: IdentifiedArrayOf<Item>
    
    init(state: LogIn.State) {
      self.items = state.items
    }
  }
  // ...
  
  var body: some View {
    WithViewStore(self.store, observe: ViewState.init) { viewState in
        //...
      }
      .refreshable {
        await self.store.send(.pullToRefresh).finish()
      }
    }
  }
}

struct LogIn: Reducer {
  struct State: Equatable {
    let id = UUID()
    var since: String? = "since"
    var items: IdentifiedArrayOf<Item> = [Item()]
  }

  enum Action {
    case pullToRefresh
    case itemLoaded(items: [Item])
  }

  var body: some ReducerOf<Self> {
    Reduce { state, action in
      switch action {
      // The first action always fail, and subsequent actions will succeed.
      case .pullToRefresh:
        state.since = nil
        
        return .run { [since = state.since] send in
          await send(.itemLoaded(items: self.loadItem(since: since)))
        }
        
      case .itemLoaded(let items):
        state.items = .init(uniqueElements: items)
        return .none
      }
    }
  }
  
  func loadItem(since: String?) async -> [Item] {
    try? await Task.sleep(for: .seconds(2))
    var items: [Item] = []
    
    for _ in 0..<20 {
      items.append(Item())
    }
    
    return items
  }
}
@heoblitz heoblitz changed the title Pull-to-refresh behavior issues Pull to refresh behavior issues Sep 25, 2023
@johnpatrickmorgan
Copy link
Owner

johnpatrickmorgan commented Sep 25, 2023

Thanks for raising this @heoblitz and for tracking down the cause! To clarify, would reinstating the lost removeDuplicates argument as in this branch fix the issue? Edit: I see in your reproduction that it does resolve the issue. Yes, I'd welcome a PR please. 🙏 I'd like to check that it's possible to avoid both this issue and the issue of going back to stale data (which was why the removeDuplicates argument was removed).

@heoblitz
Copy link
Contributor Author

heoblitz commented Sep 26, 2023

I've modified the binding logic to get the latest value instead of setting custom isDuplicated. I'll conduct some additional testing. Thank you.

Test Project
TCACoordinatorPullToRefresh.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants