Привет всем. Я работаю над проектом, в котором мне нужно обрабатывать элементы фокуса с помощью клавиш со стрелками. Прямо сейчас все в порядке, и функциональность работает по щелчку. К сожалению, когда я использую клавиши со стрелками, процесс работает для элементов tr, но он не работает для элементов ввода.
это компонент приложения:
import React from "react";
import "./App.css";
import RenderRowItem from "./RenderRow";
const keysMapNum={
LEFT:37,
UP:38,
RIGHT:39,
DOWN:40,
ENTER:13,
TAB:9,
CTRL:17
};
class App extends React.Component {
state = {
data: [],
formData: [],
selectedInput:[0,0]
};
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => response.json())
.then(json => {
const data = json.map(({ id, name, username, email }) => {
return {
id,
name,
username,
email
};
});
const mappedData=[];
data.forEach(item=>{
const rowRef=React.createRef();
const rowData=[];
Object.keys(item).forEach(innerItem=>{
let optimizedData = {
filedName:innerItem,
value:item[innerItem],
hint:false,
ref:React.createRef(),
editable:true,
visible:true,
focused:false
};
rowData.push(optimizedData);
});
const mappedDataItem = {
rowRef,
rowData,
focused:false
};
mappedData.push(mappedDataItem);
});
console.log(mappedData);
this.setState({
data:mappedData
},()=>{
console.log(this.state.data)
});
});
document.addEventListener("keydown",(e)=>{
// e.preventDefault();
const newState={...this.state};
console.log("doc",newState);
let [rowNum,columnNum]=[...newState.selectedInput];
const rowLength=newState.data.length;
const columnLength=newState.data[rowNum]["rowData"].length;
if(e.keyCode===keysMapNum.DOWN){
rowNum++;
if(rowNum>=rowLength){
rowNum=0;
}
newState.selectedInput[0]=rowNum;
this.selectedColumn(rowNum,columnNum);
this.setState({
...newState
},()=>{
this.selectedRow(rowNum,newState.data[rowNum].rowRef);
});
}else if(e.keyCode===keysMapNum.UP){
rowNum--;
if(rowNum<0){
rowNum=rowLength - 1;
}
newState.selectedInput[0]=rowNum;
this.selectedColumn(rowNum,columnNum)
this.setState({
...newState
},()=>{
this.selectedRow(rowNum,newState.data[rowNum].rowRef);
})
}else if(e.keyCode===keysMapNum.LEFT){
}else if(e.keyCode===keysMapNum.RIGHT){
}
this.setState({
...newState
})
});
}
selectedRow=(rowNum,ref)=>{
const newState={...this.state};
newState.data.forEach(item=>{
if(item.rowRef.current!==null){
item.rowRef.current.style.backgroundColor="";
item.rowRef.current.style.color="#333";
}
});
if(ref.current!==null){
ref.current.style.backgroundColor="gray";
ref.current.style.color="white";
}
// if(newState.data[rowNum]["rowData"][0].ref.current!==null){newState.data[rowNum]["rowData"][0].ref.current.focus();
// newState.data[rowNum]["rowData"][0].ref.current.select();}
};
selectedColumn=(rowNum,columnNum)=>{
const newState={...this.state};
let ref=newState.data[rowNum]["rowData"][columnNum].ref;
newState.data[rowNum]["rowData"][columnNum].ref.current.style.backgroundColor="tomato";
if(ref.current!==null){
ref.current.focus();
ref.current.select();
}
};
handleInputClick=(rowNum,columnNum)=>{
const newState={...this.state};
newState.selectedInput=[rowNum,columnNum];
newState.data[rowNum]["focused"]=true;
newState.data[rowNum]["rowData"][columnNum]["focused"]=true;
this.setState({
...newState
},()=>{
this.selectedColumn(rowNum,columnNum);
})
};
setRef=(ref)=> {
this.name = ref;
};
render() {
const { data } = this.state;
// { id, name, username, email }
return (
<div className="App">
<table>
<tbody>
{data.map((datum, rowNum) => {
return (
<tr key={rowNum} ref={datum.rowRef} onClick={()=>this.selectedRow(rowNum,datum.rowRef)}>
{datum.rowData.map((item,columnNum) => (
<RenderRowItem key={Math.random()} ref={item.ref} handleInputClick={this.handleInputClick} rowNum={rowNum} columnNum={columnNum} value={item.value} fieldName={item.filedName}/>
))}
</tr>
);
})}
</tbody>
</table>
</div>
);
}
}
export default App;
, и это компонент RowItem:
import React from "react";
const RenderRow=React.forwardRef((props,ref)=>(
<>
<td onClick={()=>props.handleInputClick(props.rowNum,props.columnNum)} >{props.filedName!=="id"?<input type="text" value={props.value} ref={ref} />:props.value}</td>
</>
));
export default RenderRow;
эта структура только тестирует, и я знаю, что ее нужно оптимизировать. Пожалуйста, используйте только стрелки вверх и вниз. Вот ссылка на SandBox