Moje podejście jest użycie ref
zwrotnego, który jest swego rodzaju onRenderComplete
elementu. W tym oddzwonieniu mogę skupić się (warunkowo, jeśli to konieczne) i uzyskać referencję dla przyszłego ogniskowania.
Jeśli dane wejściowe są renderowane warunkowo po uruchomieniu działania, to odwołanie zwrotne powinno wywołać fokus, ponieważ ref nie istnieje jeszcze bezpośrednio po wywołaniu akcji, ale dopiero po wykonaniu renderowania. Radzenie sobie z componentDidUpdate
dla takich rzeczy jak focus
wydaje się tylko bałaganem.
// Composer.jsx -- contains an input that will need to be focused somewhere else
class Composer extends Component {
render() {
return <input type="text" ref="input" />
}
// exposed as a public method
focus() {
this.refs.input.focus()
}
}
// App.jsx
@connect(
state => ({ isComposing: state.isComposing }),
...
)
class App extends Component {
render() {
const { isComposing } = this.props // or props, doesn't matter
return (
<div>
<button onClick={::this._onCompose}>Compose</button>
{isComposing ? <Composer ref={c => {
this._composer = c
this._composer && this._composer.focus() // issue initial focus
}} /> : null}
</div>
)
}
_onCompose() {
this.props.startComposing() // fire an action that changes state.isComposing
// the first time the action dispatches, this._composer is still null, so the ref takes care of the focus. After the render, the ref remains so it can be accessed:
this._composer && this._composer.focus() // focus if ref already exists
}
}
Dlaczego nie autoFocus
lub isFocued
prop?
Jak HTMLInputElement
ma value
jako rekwizyt, ale focus()
jako metody - a nie isFocused
rekwizyt - Chciałbym zachować przy użyciu metod poradzić. isFocused
może uzyskać wartość, ale jeśli użytkownik zaciera się z wejścia, co dzieje się z tą wartością? To będzie niezsynchronizowane. Ponadto, jak wspomniano w komentarzach, autoFocus
może kolidować z wieloma komponentami:
A więc jak wybierać między rekwizytami a metodami?
Dla większości przypadków rekwizytów będzie odpowiedź. Metody mogą być używane tylko w przypadku "pożaru i zapomnienia", na przykład scrollToBottom
na czacie, gdy pojawia się nowa wiadomość, scrollIntoView
i tym podobne. Są to jednorazowe zachowania, o które sklep nie dba, a użytkownik może zmienić interakcję, więc propozycja boolowska nie pasuje. W przypadku wszystkich innych rzeczy chodziłem z rekwizytami.
Oto jsbin:
http://jsbin.com/waholo/edit?html,js,output
Redux i węzłów DOM/funkcje DOM, nie mają nic wspólnego ze sobą naprawdę ... nie jestem pewien, co jak czekasz Redux być zaangażowane. Dlaczego wiele komponentów walczy o skupienie i jakiego rodzaju dziwnych zachowań próbujesz uniknąć? – azium
Jak powiedział azium, redux to tylko sposób zarządzania i przechowywania stanu aplikacji. Być może powinieneś ponownie sformułować swoje pytanie - czy pytasz o to, jak zarządzać wieloma komponentami, które mają ustawioną fokus() i kiedy są renderowane na stronie, chcesz zdecydować, która z nich rzeczywiście się skupia? Myślę, że to zależy wyłącznie od twojej aplikacji!Domyślnie byłby to ostatni, który wydawał mi się ostatni. Weź również pod uwagę atrybut "autofocus". –
Dominic, opisujesz moje obawy całkiem dobrze. Wiele komponentów, które chcą ustawić ostrość, ale wygra tylko jeden. Ostatecznie renderowany widok nie będzie zsynchronizowany z reprezentacją deklaratywną, częściowo dlatego, że z wezwaniem do fokusa() nie jest już deklaratywny, a także dlatego, że akt skupienia powoduje skutki uboczne. – jpierson