pointfreeco / swift-composable-architecture

A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind.
https://www.pointfree.co/collections/composable-architecture
MIT License
12.25k stars 1.42k forks source link

NavigationStack(path:root:destination:) not rendering root view when scoping the store into a new one. #2957

Closed danielsan22 closed 5 months ago

danielsan22 commented 5 months ago

Description

Hi all, first of all, great work on this library!

I wanted to implement navigation within the app I'm working on to learn/practice more about TCA, I implemented a new feature RootFeature that will hold the state of the stack, and added there the initial state of my top most feature to then scope it out and have it as the root of the NavigationStack(path:root:destination) view. But when building the main feature using the RootFeature I only get a white screen, that does loads and sends the initial .onTask action but never updates anything else, even when printing the changes on the reducer I can see that there is no change on the state and no other action is sent even tho the .onTask sends an array of data.

However, if I create a new store and pass it to the MainView inside the root parameter of the NavigationStack I do get the screen displaying and all the functionality that I expect, but I haven't found a way of comunicating to the parent RootFeature and get the actions that then will trigger the navigation I have defined on the RootFeature.

I am unsure if this is something that I should be doing or not or instead focus on having all the navigation logic directly inside the feature that will be the "true" root feature, but I like having my features a bit more isolated, thats why having the RootFeature take care of all the details of the other screens/features makes sense to me, it is also how I understood the docs since the examples use a simple NavigationLink as root (which to my app does not make sense to do that).

Checklist

Expected behavior

The NavigationStack's root view can be created using a scoped version of the RootFeature's store and renders and works with all the defined actions.

Actual behavior

The NavigationStack's root view is not displayed and the console prints out no changes to the sate even when they are hard-coded as when the view loads.

Steps to reproduce

I have created a brand new project and recreated the issue there.

The Composable Architecture version information

1.9.2

Destination operating system

iOS 17

Xcode version information

15.0

Swift Compiler version information

swift-driver version: 1.82.2 Apple Swift version 5.9 (swiftlang-5.9.0.114.10 clang-1500.0.29.1)
Target: arm64-apple-macosx13.0
mbrandonw commented 5 months ago

Hi @danielsan22, the problem is in the body of the RootFeature:

https://github.com/danielsan22/NavStackReproduction/blob/973142a5ef7a4e7153d7fbe2a6ef97bf7d315256/NavStackReproduction/RootView.swift#L19-L31

You aren't composing the MainFeature reducer into this at all. It should be more like this:

 var body: some ReducerOf<Self> {
+    Scope(state: \.cardsSets, action: \.cardsSets) {
+      MainFeature()
+    }
     Reduce { _, action in
         switch action {
         case .path:
             return .none
         case .cardSets:
             return .none
         }
     }
     .forEach(\.path, action: \.path) {
         Path()
     }
 }
mbrandonw commented 5 months ago

Since this isn't an issue with the library I am going to convert it to a discussion. Please feel free to continue to discuss over there.