Реагирующий ввод в строке таблицы теряет фокус на вводе

#reactjs #react-hooks #react-functional-component

#reactjs #реагирование-перехваты #реагирующий функциональный компонент

Вопрос:

Я работаю над рефакторингом нашей табличной системы для размещения динамических компонентов вместо простого текста. Я исправил все проблемы с нашей старой табличной системой, кроме одной. У меня есть поле ввода в строке таблицы для обновления перевода в нашей базе данных. По сути, каждый раз, когда вы вводите в поле ввода, ввод теряет фокус после одной буквы. Похоже, что все дерево повторно загружается. У меня есть набор ключей для каждой строки, которую я создаю в методе map. Я перепробовал все комбинации, о которых только мог подумать. Я пытался прикреплять ключи к одному элементу за раз, смешанные элементы, все дерево, все с использованием статического element_UUID с UUID, являющимся нашим идентификатором SQL UUID, который не изменится при рендеринге. Я также попытался добавить атрибуты name и id ко всем из них. Я пробовал перемещать разные функции в разные места. Я также пробовал использовать React.memo для нескольких компонентов. Я думаю, что я потенциально что-то упускаю из виду в том, как работают ключи. Я прикрепил пример codepen. Я сократил это до основной проблемы в нашей структуре таблицы.

 const startingRows = [
  {
    id: "53b8f2f2-d4ef-4e99-a8bb-bd82c6186e4f",
    key: "login",
    value: "connexion"
  },
  {
    id: "562295c5-be86-4d03-b31f-89127346096d",
    key: "name",
    value: "nom"
  },
  {
    id: "5d3b7d33-bf74-4ea2-ab15-3220ebe9d9e9",
    key: "password",
    value: null
  }
];

const useForm = () => {
  const [inputs, setInputs] = React.useState({});

  const handleInputChange = (e) => {
    e.persist();
    setInputs((inputs) => ({
      ...inputs,
      [e.target.name]: e.target.value
    }));
  };

  return {
    handleInputChange,
    inputs
  };
};

const Show = () => {
  const { inputs, handleInputChange } = useForm();
 
  const tableProps = {
    // Passing in the root components high level state that's required in the TableRows
    TableRow: TableRow({
      inputs,
      handleInputChange
    }),
    rows: { count: 3, records: startingRows }
  };

  return <Table {...tableProps} />;
};

const Table = ({ TableRow, rows: { count, records } }) => {
  return <TableContent TableRow={TableRow} rows={records} />;
};


// It's my understanding that the key below
// attached to the TableRow in the map method
// is what allows React to differeniate between
// what needs to be updated and what doesn't
const TableContent = ({ TableRow, rows }) => {
  return (
    <table>
      <thead>
        <tr>
          <th>Word</th>
          <th>Translation</th>
        </tr>
      </thead>
      <tbody>
        {rows amp;amp; rows.map((row) => <TableRow key={row.id} row={row} />)}
      </tbody>
    </table>
  );
};

const TableRow = ({ handleInputChange, inputs }) => ({
  // key in this sense means a locale key
  row: { id, key, value }
}) => {
  return (
    <tr>
      <td>{key}</td>
      <td>
        <Input
          name={id}
          onChange={handleInputChange}
          value={inputs[id] || value}
        />
      </td>
    </tr>
  );
};

const Input = ({ id, name, onChange, value }) => {
  return <input name={name} onChange={onChange} value={value} />;
};

ReactDOM.render(<Show />, document.getElementById("root"));  
 body {
  height: 100vh;
  margin: 0;
  display: grid;
  place-items: center;
}
.box {
  width: 300px;
  h1 {
    font-size: 20px;
    margin: 0 0 1rem 0;
  }
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0-alpha.0/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap-sass@3.4.1/assets/javascripts/bootstrap.min.js"></script>
<div id="root"></div>  

codepen

Любая помощь была бы высоко оценена!

Комментарии:

1. Ваш код повторно отображает тег body при изменении ввода из-за изменения состояния using setInputs . По мере обновления состояния компоненты повторно отображаются снова. Что вы можете сделать, так это отслеживать последний ввод / startingRows ввод в json, а затем использовать его при фокусировке.

Ответ №1:

Вам нужно снова добавить фокус, когда компонент отображается с помощью ref для этого измените свой входной компонент на этот. Я попробовал это, это работает.

 const Input = ({ id, name, onChange, value }) => {
     React.useEffect(()=>{
        this.nameInput.focus();
  })
  
  return <input name={name}
           ref={(input) => { this.nameInput = input; }} 
           onChange={onChange} value={value} />;
};
  

Комментарии:

1. Это действительно кажется шагом в правильном направлении. Для первого, на который я нажимаю, он сохраняет фокус, но как только вы переключаете входные данные и вводите символ, он переключает фокус на первый.