Acabei de encontrar este problema e estou usando o react 15.0.1 15.0.2 e estou usando a sintaxe ES6 e não obtive o que precisava das outras respostas desde que a v.15 caiu semanas atrás e algumas das this.refs
propriedades foram preteridos e removidos .
Em geral, o que eu precisava era:
- Focalize o primeiro elemento de entrada (campo) quando o componente for montado
- Focalize o primeiro elemento de entrada (campo) com um erro (após o envio)
Estou a usar:
- Reagir recipiente / componente de apresentação
- Restaurado
- React-Router
Focar o primeiro elemento de entrada
Eu usei autoFocus={true}
o primeiro <input />
na página para que, quando o componente for montado, ele tenha foco.
Focar o primeiro elemento de entrada com um erro
Isso levou mais tempo e foi mais complicado. Estou mantendo fora do código que não é relevante para a solução por questões de brevidade.
Loja / Estado Redux
Eu preciso de um estado global para saber se devo definir o foco e desabilitá-lo quando foi definido, para não continuar redefinindo o foco quando os componentes forem renderizados novamente (usarei componentDidUpdate()
para verificar a definição do foco. )
Isso pode ser projetado da maneira que você achar melhor para sua aplicação.
{
form: {
resetFocus: false,
}
}
Componente Container
O componente precisará ter a resetfocus
propriedade definida e um callBack para limpar a propriedade, se acabar definindo o foco em si mesmo.
Observe também que organizei meus Action Creators em arquivos separados, principalmente devido ao meu projeto ser bastante grande e que eu queria dividi-los em partes mais gerenciáveis.
import { connect } from 'react-redux';
import MyField from '../presentation/MyField';
import ActionCreator from '../actions/action-creators';
function mapStateToProps(state) {
return {
resetFocus: state.form.resetFocus
}
}
function mapDispatchToProps(dispatch) {
return {
clearResetFocus() {
dispatch(ActionCreator.clearResetFocus());
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyField);
Componente de apresentação
import React, { PropTypes } form 'react';
export default class MyField extends React.Component {
// don't forget to .bind(this)
constructor(props) {
super(props);
this._handleRef = this._handleRef.bind(this);
}
// This is not called on the initial render so
// this._input will be set before this get called
componentDidUpdate() {
if(!this.props.resetFocus) {
return false;
}
if(this.shouldfocus()) {
this._input.focus();
this.props.clearResetFocus();
}
}
// When the component mounts, it will save a
// reference to itself as _input, which we'll
// be able to call in subsequent componentDidUpdate()
// calls if we need to set focus.
_handleRef(c) {
this._input = c;
}
// Whatever logic you need to determine if this
// component should get focus
shouldFocus() {
// ...
}
// pass the _handleRef callback so we can access
// a reference of this element in other component methods
render() {
return (
<input ref={this._handleRef} type="text" />
);
}
}
Myfield.propTypes = {
clearResetFocus: PropTypes.func,
resetFocus: PropTypes.bool
}
Visão geral
A ideia geral é que cada campo de formulário que possa ter um erro e ser focado precise se verificar e se precisar definir o foco em si mesmo.
Há uma lógica comercial que precisa acontecer para determinar se o campo especificado é o campo certo para definir o foco. Isso não é mostrado porque dependerá do aplicativo individual.
Quando um formulário é enviado, esse evento precisa definir o sinalizador de foco global resetFocus
como true. Então, à medida que cada componente se atualiza, ele verifica se obtém o foco e, se obtém, despacha o evento para redefinir o foco para que outros elementos não precisem continuar verificando.
edit
Como observação, eu tinha minha lógica de negócios em um arquivo "utilitários" e acabei de exportar o método e o chamei em cada shouldfocus()
método.
Felicidades!