#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>
Любая помощь была бы высоко оценена!
Комментарии:
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. Это действительно кажется шагом в правильном направлении. Для первого, на который я нажимаю, он сохраняет фокус, но как только вы переключаете входные данные и вводите символ, он переключает фокус на первый.