В Inferno, как и в других современных UI-фреймворках на основе
виртуального DOM, управление состоянием компонентов является ключевым
аспектом построения реактивного интерфейса. Компоненты могут иметь
локальное состояние, определяемое через this.state в
классовых компонентах или useState в функциональных
компонентах.
Локальное состояние удобно для внутренних нужд компонента, но часто возникает необходимость синхронизации состояния между несколькими компонентами. В таких случаях используется подъем состояния (lifting state up).
Подъем состояния заключается в переносе состояния из дочернего компонента в родительский, который затем передает это состояние обратно через пропсы. Такой подход обеспечивает единую точку правды, устраняет дублирование данных и упрощает управление взаимодействием компонентов.
Пример структуры компонентов с подъемом состояния:
import { Component } from 'inferno';
class TemperatureInput extends Component {
handleChange = (e) => {
this.props.onTemperatureChange(e.target.value);
};
render() {
const { temperature } = this.props;
return (
<fieldset>
<legend>Введите температуру:</legend>
<input value={temperature} onIn put={this.handleChange} />
</fieldset>
);
}
}
class Calculator extends Component {
state = { temperature: '' };
handleTemperatureChange = (temperature) => {
this.setState({ temperature });
};
render() {
return (
<div>
<TemperatureInput
temperature={this.state.temperature}
onTemperatureCha nge={this.handleTemperatureChange}
/>
</div>
);
}
}
В этом примере состояние temperature поднимается в
компонент Calculator, который контролирует данные и
передает их в дочерний TemperatureInput через пропсы.
Преимущества подъемного состояния:
Паттерн контейнер-представление разделяет компоненты на два типа:
Такое разделение улучшает читаемость кода, облегчает тестирование и повторное использование компонентов.
// Презентационный компонент
const UserList = ({ users, onUserClick }) => (
<ul>
{users.map(user => (
<li key={user.id} onCl ick={() => onUserClick(user)}>
{user.name}
</li>
))}
</ul>
);
// Контейнерный компонент
class UserContainer extends Component {
state = { users: [], selectedUser: null };
componentDidMount() {
fetch('/api/users')
.then(res => res.json())
.then(users => this.setState({ users }));
}
handleUserClick = (user) => {
this.setState({ selectedUser: user });
};
render() {
return (
<UserList
users={this.state.users}
onUserCl ick={this.handleUserClick}
/>
);
}
}
В данном примере UserContainer управляет состоянием
списка пользователей и выбранного пользователя, а UserList
исключительно отображает данные.
Ключевые моменты паттерна:
Эти два подхода тесно связаны. Контейнерный компонент часто выступает в роли родителя, в котором поднимается состояние, необходимое для дочерних презентационных компонентов. Это обеспечивает:
Эти подходы формируют основу архитектуры приложений на Inferno, позволяя создавать предсказуемые, масштабируемые и легко поддерживаемые интерфейсы.