State Hoisting
State hoisting в Jetpack Compose — это паттерн управления состоянием, при котором состояние "поднимается" (hoisted) из дочернего компонента в родительский. Это делается для того, чтобы управление состоянием было вынесено за пределы компонента и могло изменяться или контролироваться извне.
Представь, что у тебя есть несколько компонентов, которые должны работать с одним и тем же состоянием. Если состояние будет управляться каждым компонентом отдельно, это создаст сложности при взаимодействии между ними. State hoisting помогает централизовать состояние, делая его доступным для всех нужных компонентов.
State hoisting основывается на двух вещах:
Это позволяет родителю контролировать состояние, а дочерние компоненты только отображают данные или вызывают функцию для их обновления.
Вот простой пример текстового поля, где состояние (введённый текст) управляется внутри компонента MyTextField
:
@Composable
fun MyTextField() {
var text by remember { mutableStateOf("") }
TextField(
value = text,
onValueChange = { newText ->
text = newText
}
)
}
Здесь состояние text
хранится и обновляется внутри MyTextField
. Это нормально, если это поле не должно взаимодействовать с другими частями приложения. Но что если текст нужно использовать в родительском компоненте?
Теперь мы поднимем состояние "наверх", чтобы родительский компонент контролировал его. Для этого нужно передать в MyTextField
два параметра: текущее состояние и функцию для его обновления.
@Composable
fun MyTextField(text: String, onTextChange: (String) -> Unit) {
TextField(
value = text,
onValueChange = { newText ->
onTextChange(newText)
}
)
}
Теперь MyTextField
больше не хранит состояние самостоятельно. Вместо этого оно передаётся извне через параметр text
, а функция onTextChange
обновляет это состояние.
Теперь родитель может управлять состоянием:
@Composable
fun Parent() {
var text by remember { mutableStateOf("") }
MyTextField(
text = text,
onTextChange = { newText ->
text = newText
}
)
}
Здесь состояние text
находится в компоненте Parent
, и оно передаётся в дочерний MyTextField
. Когда пользователь вводит новый текст, функция onTextChange
обновляет это состояние в родительском компоненте.
Представим, что у нас есть текстовое поле и текстовый блок, которые должны показывать одно и то же значение:
@Composable
fun MyTextField(text: String, onTextChange: (String) -> Unit) {
TextField(
value = text,
onValueChange = onTextChange
)
}
@Composable
fun MyTextDisplay(text: String) {
Text(text = text)
}
@Composable
fun Parent() {
var text by remember { mutableStateOf("") }
Column {
MyTextField(text = text, onTextChange = { newText -> text = newText })
MyTextDisplay(text = text)
}
}
В этом примере родительский компонент Parent
управляет состоянием text
, а дочерние компоненты просто получают это состояние и/или вызывают функцию для его обновления.