Фокусировка на элементе ввода с использованием ссылки не работает - PullRequest
0 голосов
/ 07 февраля 2020

Привет всем. Я работаю над проектом, в котором мне нужно обрабатывать элементы фокуса с помощью клавиш со стрелками. Прямо сейчас все в порядке, и функциональность работает по щелчку. К сожалению, когда я использую клавиши со стрелками, процесс работает для элементов 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...