<@UHAJKUSTU> I have made a component using Compone...
# decompose
s
@Arkadii Ivanov I have made a component using ComponentContext that is kinda applicationCOntxet, is there any way i can clear or destroy this component after i am done with all operations. The reason for creating using ComponentCOntext is i wanted to use same compont with same instance of store and storefactory across 2-3 different screens. is my approcach correct?
a
Can you describe how you create your component?
s
In the main root component , i have these two declarations :-
createNewOrder = *{* childContext, projectId, isOpenedFromBOQ, orgId, immediateClientId, context, openFrom, orderDetailsRes, output *->*
CreateNewOrderComponent(
componentContext = componentContext,
storeFactory = storeFactory,
projectId = projectId,
isOpenedFromBOQ = isOpenedFromBOQ,
orgId = orgId,
immediateClientId = immediateClientId,
context = context,
openFrom = openFrom,
orderDetailsRes = orderDetailsRes,
output = output,
)
*}*,
createNewOrderStep2 =
*{* childContext, projectId, isOpenedFromBOQ, orgId, immediateClientId, clientId1, output *->*
CreateNewOrderComponent(
componentContext = componentContext, // childContext
storeFactory = storeFactory,
projectId = projectId,
isOpenedFromBOQ = isOpenedFromBOQ,
orgId = orgId,
immediateClientId = immediateClientId,
clientId = clientId ?: clientId1,
output = output,
)
*}*,
for step1 and step2
In RootContent i have corresponding screens for them, i have created these two usinf ComponentContext rather thatn childCOntext
Copy code
class CreateNewOrderComponent(
    componentContext: ComponentContext,
    storeFactory: StoreFactory,
    var projectId: String,
    val clientId: String? = null,
    val libraryId: String? = null,
    val isOpenedFromBOQ: Boolean,
    val orgId: String?,
    val immediateClientId: String?,
    val orderItem: OrderElementCreateData? = null,
    val preFilledPODetails: AddPOResponseModel? = null,
    val context: String? = null,
    val openFrom: String? = null,
    val orderDetailsRes: OrderDetailResModel? = null,
    private val output: (Output) -> Unit,
) : ComponentContext by componentContext {

    private val createNewOrderStore = instanceKeeper.getOrCreate {
        CreateNewOrderStoreFactory(
            storeFactory = storeFactory,
            projectId = projectId
        ).create()
    }

    @OptIn(ExperimentalCoroutinesApi::class)
    val state = createNewOrderStore.stateFlow

    fun onEvent(event: CreateNewOrderStore.Intent) {
        println("createNewOrderStore ${createNewOrderStore}")
        createNewOrderStore.accept(event)
    }

    fun onOutput(output: Output) {
        output(output)
    }

    fun clearStore() {
        createNewOrderStore.dispose()
    }
}
a
Got it, thanks! The way those two components are created looks incorrect. There should be separate instance of ComponentContext for each child component. I would either use childContext, or Child Slot if I need to create/destroy manually.
s
but when using childContext, i have to create different instance of store and storefactory in both components
i want to use same instance of store and storefactory across these two components how can i do that. @Arkadii Ivanov. i.e suppose i have saved some data in step1 now using the same store and state i want to read data in step2
a
Well, in this case you can create and pass the store instance from outside. You can also extract both child components into a separate holding component, which would also create the store.
s
how can we pass the store instance, components only accepts parcelable data? like this :
@Parcelize
data class CreateNewOrderScreenStep2( val projectId: String?, val isOpenedFromBOQ: Boolean, val orgId: String?, val immediateClientId: String?, val clientId: String?, ) : Configuration()
a
Oh, you can just pass manually in the place where you call the component constructor. The same way as we pass callback lambdas.
s
Copy code
class RootComponent internal constructor(
    componentContext: ComponentContext, private val createNewOrderStep2: (ComponentContext, projectId: String, isOpenedFromBOQ: Boolean, orgId: String?, immediateClientId: String?, clientId: String?, (CreateNewOrderComponent.Output) -> Unit) -> CreateNewOrderComponent)
u mean here?
a
That could work as well. You can add the store as an additional argument to the factory function createNewOrderStep2.
s
Nut when creating child
is Configuration.CreateNewOrderScreenStep2 -> Child.CreateNewOrderScreenStep2(
createNewOrderStep2( componentContext, configuration.projectId ?: "", configuration.isOpenedFromBOQ, orgId ?: configuration.orgId, immediateClientId ?: configuration.immediateClientId, configuration.clientId, null, // what to put here for store, ::onCreateNewOrderScreenOutput ) ). / what to put here for store,? we cant get that data from configuration?
a
It looks like you have a multi step flow for creating a user. I would extract the flow to a separate CreateUserComponent, and host the shared store in there. As well as all child Step components (perhaps in a stack).
s
any example of shared store?
a
Unfortunately there is nothing I'm aware of. But it's pretty simple. In CreateUserComponent, create the store and assign it to a private property. Then just pass the store reference to every child component constructor.
s
YEs, got it, i was missing it , i used it in many places
for some othe scenarios , thanks @Arkadii Ivanov for quick help
👍 1
a
Glad to help!
👍 1