Ввод фокуса после отправки скидки
Я динамически создаю список входов с React и Redux. После нажатия кнопки ввод добавляется в конец списка. Мне нужно сфокусировать последний добавленный ввод. Я пробовал этот код, но он фокусирует предпоследний вход
const mapDispatchToProps = (dispatch, ownProps) => ({
onOptionsChange: (newOptions) => {
dispatch(formActions.updateOptions(newOptions));
}
});
...
this.props.onOptionsChange({ ...this.props, inputsList}); // change list of inputs
ReactDOM.findDOMNode(this.inputs[this.props.choices.length - 1]).focus();
В журналах я вижу, что focus() выполняется до обновления реквизита из состояния. Как подождать окончания отправки?
Ответы
Ответ 1
Я бы выполнил componentDidUpdate
и проверил длину вашего "входного массива" или любой другой структуры данных, которую вы используете:
componentDidUpdate(prevProps, prevState) {
if (prevProps.choices.length < this.props.choices.length) {
ReactDOM.findDOMNode(this.inputs[this.props.choices.length - 1]).focus();
}
}
Ответ 2
Продвигайте свою рассылку
Позволяет написать промежуточное программное обеспечение, которое возвращает обещание после завершения отправки.
const thenMiddleware = store => next => action => {
return new Promise((resolve, reject) => {
try {
resolve(next(action));
} catch(e) {
reject(e);
}
})
};
Сначала подготовьте свой магазин, установив промежуточное ПО
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers/index';
/**
* Our star of the show
*/
const thenMiddleware = store => next => action => {
return new Promise((resolve, reject) => {
try {
resolve(next(action));
} catch(e) {
reject(e);
}
})
};
const store = createStore(
rootReducer,
applyMiddleware(thenMiddleware)
);
Теперь нам нужно вернуть отправку внутри нашего метода mapDispatchToProps
const mapDispatchToProps = (dispatch, ownProps) => ({
onOptionsChange: (newOptions) => {
return dispatch(formActions.updateOptions(newOptions));
}
});
Наконец, завершите свое мероприятие полным
Теперь, когда вы знаете, какой вход вы создали в последний раз,
вы можете прикрепить к этой отправке полную функцию.
this.props.onOptionsChange(newOptions).then(() => {
// do your input focusing here
});
Ответ 3
Создайте новый компонент упаковки для элемента input
. Этот компонент будет автофокусироваться при визуализации.
class Input extends React.Component {
keepRef = (ref) => {
this.ref = ref;
}
componentDidMount() {
this.ref.focus();
}
render () {
return (
<input ref={this.keepRef} {...this.props} />
)
}
}
Если вы не хотите, чтобы компонент input
обрабатывал фокус, переместите логику в его родительский.
Ответ 4
Я столкнулся с аналогичной проблемой, в которой у меня был список элементов, и мне нужно сосредоточиться на последнем элементе всякий раз, когда добавляется новый элемент. В приведенном ниже коде используется флюсовая архитектура, но я думаю, он должен решить вашу проблему.
addNewItem: function() {
var self = this;
var list = this.state.list || {};
var listOrder = this.state.listOrder || [];
var newKey = "some_random_key";
list[newKey] = {
"product": ""
};
listOrder.push(newKey);
this.state.list = list;
this.state.listOrder = listOrder;
this.setState({list: this.state.list, listOrder: this.state.listOrder, showSaveButton: true});
setTimeout(function(){
$(".buy-form-item-list-row .buy-form-item-list-item-name").last().focus();
}, 0);
},
Итак, в приведенном выше коде..
listOrder содержит ключи списка элементов. Например:
list - это объект, который содержит элемент. Например:
listOrder = [ran_1, ran_2];
список = { ran_1: { продукт: "Яйца - 5" }, ran_2: { продукт: "Хлеб - 1" }
}
метод рендеринга, перебираем listOrder и создаем тег ввода с классомName = "buy-form-item-list-item-name" для каждого элемента.
Трюк для фокусировки на последнем элементе - это setTimeout с интервалом 0. Когда вы вызываете setState, он не запускает функцию рендеринга в тот момент сам, вместо этого он ожидает, что функция будет выполнена полностью.
Надеюсь, это поможет.