Reading codelabs… It says `TextField` is stateless...
# compose
a
Reading codelabs… It says
TextField
is stateless, but
TextFieldImpl
as a bunch of mutable states internally. How do we know if a Composable is stateless or not?
👀 1
👍 1
a
In this case the codelab is hand-waving a bit and referring to the kind of state your app interacts with, rather than some of the internal state that a composable might maintain to keep that abstraction. You still own the source of truth for the TextField's current value and control when it changes, but the TextField keeps some internal state around the connection to the Android soft keyboard, and some conveniences around selection state if your code wants to work in strings instead of the text field values that include selection state
On top of that, we do have some planned work in the area of TextFields that will probably reduce the internal state tracking. Some of the implementation there was designed to work around early compose compiler/runtime limitations or bugs that no longer apply.
👍 4
s
Yep – author here. Intentionally did some hand waving (for example, the blinking cursor is state – and the current TextField(String, (String) -> Unit) implementation does maintain duplicated state that's transparently updated).
The big idea to get across is that we intend to provide the ability to hoist state from any built-in widget. At alpha this is not universally true for all APIs, but expect more of it instead of moving towards unhostable state.
In practice, especially when making library-like composables like
TextField
– the actual state management is a more complex than a simple statefull/stateless division (though the same analysis applies – TextField is more complex due to it's internal state). The goal of that was to teach practical state hoisting techniques as that's the big change moving to declarative. We're also finding with
TextField
and similar composables we've built that have duplicated state this can be a double edged sword as the duplicated state introduces the ability of update errors. Currently in
TextField
if you back the text state with an async updated state holder, it's possible to show characters before they're applied, or even drop characters. As Adam said some more work is coming on this particular API.
For the question "How do I know if a composable is stateless or not." In general, you shouldn't need to care as a caller. The existence of internal state is entirely an implementation detail of a composable. In practice, ripples, cursor animations, scrolling, crossfade animations, paging, tab selection, checkbox animations, etc all add internal state to a composable. Where it matters is if there is underhosted state, That's a composable that doesn't provide you an interface for controlling state when you need it.
Not used in that codelab, but
TextField
also provides an override that allows you to hoist the edit text state completely. This API was avoided in the codelab since ergonomics of this API require hosting a data class and introduced a bunch of unrelated and likely-to-be-changed concepts.
@allan.conda I'm thinking of updating the definitions of stateless/stateful in that codelab to be more accurate in this case without introducing a larger nomenclature to describe composables.
Copy code
A stateless composable with respect to a particular state cannot directly change that state.

A stateful composable with respect to a particular state can directly change that state.
I'd love input on this!
(the other route is to introduce a secondary axis of controlled/uncontrolled, which is another useful way to think about this problem)
a
🤔 I’m not sure… it makes it more confusing I think. It seems a composable can be both stateless and stateful depending on which state is being referred to, based from those definitions
Not sure what the other route means. How about simpler definitions such as :
Copy code
Built-in composable are designed using unidirectional data flow, and aims to be stateless. 

A stateless composable does not own state and cannot change directly, and pushes up events to the owner of state that can change it.

A stateful composable maintain a lot of internal state and can change them directly.

(<if actually stateless as defined above> Most built-in composables are stateless.) Some built-in composables may own state for convenience, such as the TextField's cursor state so consumers do not always have to manually handle them.
I may be wrong about the built-in composables 🙂 Stateless should purely mean “does not own state” imo. Stateful is more subjective (maybe a composable should not be considered stateful if it only maintains a single simple state)
s
Makes sense to me – and yea it appears there's a bit of a gray area between stateless and stateful
For example, if a composable calls animateLayoutChanges, it's technically stateful but not in a way that I would typically use the term
👍 1
Thanks for feedback! I'll keep the definitions simple and then be more precise in that callout there.
a
appreciate your request for input and improving the codelab 🙂