Когда использовать реквизиты, а когда состояние в подкомпонентах Preact
Я изучаю preact, но это может касаться и React.
Скажем, у меня есть список флажков, каждый из которых имеет некоторый дополнительный HTML, например так (Typescript):
export class MyCheckbox extends Component<Props, State> {
render(props, state) {
return (
<div>
<input
type="checkbox"
checked={state.checked}
onChange={props.onUpdate}
/>
<div>
{props.name}
<!-- other GUI elements -->
</div>
</div>
);
}
}
Затем эти компоненты используются в компоненте более высокого уровня, например:
render(props, state) {
return (
<div class={style.finding}>
<form>
{ this.elements
.map(el => (
<MyCheckbox name={el.name} checked={el.checked} onUpdate={this.onUpdate()} />
))
}
</form>
</div>
</div>
);
Как вы можете видеть, компонент более высокого уровня сообщает флажок, должен ли он быть установлен или нет. Итак Props
Объект флажка имеет свойство checked
на нем, который определяет, должен ли быть установлен флажок, когда он становится видимым.
Однако нам также нужен checked
собственность на State
, потому что пользователь может установить флажок и, таким образом, обновить его. Так Props.checked
означает "изначально проверено" и State.checked
означает "в настоящее время проверено".
Но если пользователь нажимает флажок, onUpdate
метод обновит this.elements
модель на компоненте более высокого уровня. Это сработает render()
на компоненте более высокого уровня, который в свою очередь передает новый Props.checked
на флажок.
Это означает, что Props
из флажка будет действовать как состояние. Оно обновляется, когда пользователь нажимает на флажок, и затем новое состояние передается флажку.
Это нормально? Или мой дизайн как-то выключен? Нужно ли вообще дочернему компоненту состояние?
1 ответ
Обычно выходом является применение шаблона Stateful parent и childless child.
В вашем случае MyCheckbox должен быть без сохранения состояния (не должен содержать checked
переменная состояния) и проверяемое значение должно быть свойством.
Состояние проверяемого значения должно обрабатываться родительским состоянием.
export class MyCheckbox extends Component<Props, State> {
render(props, state) {
return (
<div>
<input
type="checkbox"
checked={props.checked}
onChange={props.onUpdate} />
<div>
{props.name}
<!-- other GUI elements -->
</div>
</div>
);
}
}
родитель:
export class Parent extends Component<Props, State> {
...
render(props, state) {
return (
<div class={style.finding}>
<form>
{ this.elements
.map(el => (
<MyCheckbox name={el.name} checked={this.isChecked(el)} onUpdate={this.onUpdate()} />
))
}
</form>
</div>
</div>
);
isChecked(elem) {
// use this.state to verify to return a boolean representing the checkbox checked state
}
}
Делать компонент без сохранения состояния всегда хорошо. Наличие опоры и значения состояния, представляющих один и тот же аспект компонента, немного уродливо.
Надеюсь это поможет