Hey people, I recently used `@Preview` extensively...
# compose
s
Hey people, I recently used
@Preview
extensively and I would say that providing all the fake data sometimes gets repetitive. Doing for example
getFakeUserModel(id)
functions work great, but… where do you put those? Where in the package structure do you put your fake preview data? And polluting every class with something like
Copy code
data class Whatever(...) {
    companion object {
        fakePreviewWhatever(something: String): Whatever
    }
}
is not necessarily something that I love doing. At the rate that I am doing it now, a big chunk of my files in the package structure would need to be there just to provide fake models which sounds like a great way to confuse newcomers to the codebase. Any tips or tricks on how to do this better?
f
I'm probably doing it wrong but I just add the fake data right in my Preview functions and then put these preview functions at the end of the file so it doesn't bother me while going through the real stuff
s
That is definitely doable. What I have trouble with in this case is that some model classes are shared across files, then this fake model builder function goes in which file? I can just keep it where I initially created it, sure but this absolutely does not feel right. And the problem with just creating the models in-line, inside the preview is that then often I have let’s say a preview that’s 30 lines. 5 is the UI and 25 is this huge model class that has other nested classes etc. And then when I need to use this fake data in another preview, I need to copy those entire 25 lines to that preview too, that’s a huge no for me.
w
We try to avoid passing models into our base composables (which are more tested, and live in a separate module)
h
Depends on your structure. I am using a mono repo for all code, backend, web and iOS, Android, so I put all my test/fake data in a extra module to use the same test data again.
s
Still, composables often need a lot of data passed into them, what do you mean you do not pass models into them, how are things passed into them then? A separate module sounds interesting, definitely high on the effort scale, but something to keep in mind if my preview needs reach that point.
w
We have 2 types of composables- base composables and view composables. Base composables largely take primitives (or other composables) as their input, and are put into a separate module. View composables take our ViewModels and apply them to the UI. Most of them are pretty straightforward, and follow our standard design constants- cards, RadioButtonTextLists, Banners, Chips- these are all standard throughout our application, so our ViewComposables are usually just a stack of a list or a few children
We also have all of our VMs expose a single ViewState object, which has a bunch of default values, so you could adjust your composables to accept a Flow<ViewState> for its content then use the default values?
s
My VMs also expose a single ViewState object, but the defaults are often an empty Loading state, or in general not always the only thing I want to see on my previews, so passing the default ViewState is not really enough by itself. Do you have any code samples of the previews you can share that I can look at? I might have lost you somewhere there but I still don’t really see how the problem is solved.
i
If your Composable accepts a
Flow<ViewState>
, then your Preview can offer a
flowOf(LoadingState)
or a
flowOf(SomeComplicatedState(input = "withFakeData"))
- you have full control at that point of what your Flow contains