var name by remember { mutableStateOf("") }
OutlinedTextField(
value = name,
onValueChange = { name = it },
label = { Text("Name") }
)
Compose의 UI는 수정될 수 없음.
UI 상태가 변경될 때만 변경된 UI 트리를 다시 만듬.
TextField는 값을 받고 onValueChange를 노출함.
상태를 노출하고 이벤트를 노출. -> 단방향 데이터 흐름이 적합.
(Unidirectional Data Flow)
상태는 위애서 아래로, 이벤트는 아래에서 위로 단방향

이벤트: UI의 일부에서 이벤트를 생성해 위로 전달.
뷰 모델에서 처리하는 버튼 클릭, 사용자 세션의 만료됨을 표현하는 앱의 다른 레이어에서 전달되는 이벤트.
상태 갱신: 이벤트 핸들러가 상태를 바꿉니다.
상태 표시: 스테이트 홀더가 아래로 전달한 상태를 UI가 표시합니다.
테스트 가능성: 상태를 표시하는 UI와 상태를 분리하면, 둘을 분리해 쉽게 테스트할 수 있습니다.
상태 캡슐화: 상태가 한 곳에서만 갱신될 수 있으면, 컴포저블 상태를 위한 단일 정보 진실원(SSOT, single source of truth)가 될 수 있고, 일관되지 않는 상태 때문에 발생하는 버그를 줄일 수 있다.
UI 일관성: StateFlow와 LiveData와 같은 관측가능한 상태 홀더를 사용해 UI에 상태 갱신을 즉각 반영할 수 있다.
컴포저블은 상태와 이벤트에 따라 동작한다.
TextField는 value 파라미터가 갱신될 때만 갱신된다.
onValueChange 콜백을 노출하는데, 값을 새로운 값으로 바꾸는 요청을 하는 이벤트이다.
컴포즈는 값 홀더로 State 객체를 정의, 상태 값의 변경은 리컴포지션을 유발한다.
remember, rememberSaveable로 상태를 저장.
TextField의 value는 String, 하드코딩된 값, ViewModel로, 부모 컴포저블에서 받을 수 있고, 상태일 필요가 없음.
값은 onValueChange 호출로 변경.
mutableStateOf는 Compose가 관측할 수 있는 타입인 MutableState를 만든다.
값이 변경되면 값을 읽는 모든 컴포지션 함수의 리컴포지션을 예약한다.
remember는 객체를 컴포지션에 저장하고, remeber를 호출한 컴포저블이 컴포지션에서 제거될 때 객체를 잊는다.
rememberSavable은 객체를 Bundle에 저장해 configuration이 변경되
어도 유지한다.
@Composable
fun Header(title: String, subtitle: String) {
// Recomposes when title or subtitle have changed.
}
@Composable
fun Header(news: News) {
// Recomposes when a new instance of News is passed in.
}
첫 번째 Header는 title이나 subtitle이 갱신되면 리컴포지션이 되는데, 아래는 News 중 일부가 변경되면 리컴포지션.
Header에서 title와 subtitle만 쓴다면 아래와 같이 짜는 것이 좋지 않음.