私は<input>
のリストであるインターフェースを持っています。いずれかの入力でEnterキーを押すと、次の入力にフォーカスが移ります。最後の入力になっている場合は、もう1つを追加し、もう1つはフォーカスします。アイテムのリストはreduxによって管理されます。ここで 還元状態変更後のDOM操作の処理
class ListItem extends Component {
render() {
return (
<li>
<input
defaultValue={this.props.value}
onKeyUp={this.onKeyUp.bind(this)}
ref={(input) => this.input = input}
/>
</li>
);
}
onKeyUp(event) {
this.props.onChange(event.target.value, event.keyCode === 13);
}
focus() {
this.input.focus();
}
}
class List extends Component {
render() {
return (
<ul>
{this.props.items.map((item, i) =>
<ListItem
key={i}
value={item}
onChange={(value, enterPressed) => this.onChange(i, value, enterPressed)}
/>
)}
</ul>
);
}
onChange(i, value, enterPressed) {
this.props.dispatch({
type: 'UPDATE_ITEM',
index: i,
value: value
});
if (enterPressed && i === this.props.items.length - 1) {
this.props.dispatch({
type: 'ADD_ITEM'
});
}
}
}
我々はそれを集中したいとき、次のリスト要素がまだ存在しない場合がありますので、これは、本当に難しいと思われるので、私たち何とかredux状態の変化が起こるまで待つ必要があり、リストは最後の項目と並び直します。
私が考えることができる唯一の方法は、リスト項目のそれぞれに参照配列を格納し、Enterを押したときにreduxイベントを送出し、コンポーネント状態でフォーカスされたリスト項目のインデックスを設定することです。次に、componentDidUpdate(redux状態が更新され、余分な入力がDOMにある場合に呼び出されます)で、どの入力をフォーカスする必要があるかを確認し、フォーカスメソッドを呼び出します。
class List extends React.Component {
constructor(props) {
super(props);
this.inputs = [];
}
render() {
return (
<ul>
{this.props.items.map((item, i) =>
<ListItem
key={i}
value={item}
onChange={(value, enterPressed) => this.onChange(i, value, enterPressed)}
ref={(input) => this.inputs[i] = input}
/>
)}
</ul>
);
}
onChange(i, value, enterPressed) {
this.props.dispatch({
type: 'UPDATE_ITEM',
index: i,
value: value
});
if (enterPressed) {
this.setState({
inputToFocus: i + 1
})
if (i === this.props.items.length - 1) {
this.props.dispatch({
type: 'ADD_ITEM'
});
}
}
}
componentDidUpdate() {
if (typeof this.state.inputToFocus === 'number') {
this.inputs[this.state.inputToFocus].focus();
this.setState({
inputToFocus: null
});
}
}
これは本当に壊れやすいと醜い感じています。それを行うより良い方法はありますか?
完全な例はhttps://jsfiddle.net/69z2wepo/59903/です。
ListItemはどのような方法でフォーカスする必要がありますか? isFocusedフラグがフォーカスされた後にunsetされますか? –
これはcomponentDidMountとcomponentDidUpdate(同じコードを2回複製しないようにメソッドを呼び出すことができます)、本質的にif(this.props.isFocused)this.input.focusのようなものでなければなりません。 – luanped
フラグがフォーカスされた後にフラグを解除する必要はありません。基本的には、propsを真実のソースにすることができます。ただ1つのListItemだけがisFocused trueを持つようにする必要があります。 – luanped