Не работает корректно поиск. К пример, ввожу 1 - ноль эмоций, на 11 он начинает искать как 1, на 111 он начинает искать на 11 и т.д.
import React, { useState, useEffect, useRef, useCallback } from 'react';
import axios from 'axios';
import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
const limit = 20;
const Table = () => {
const [items, setItems] = useState([]);
const [selectedIds, setSelectedIds] = useState([]);
const [search, setSearch] = useState('');
const offsetRef = useRef(0);
const loadingRef = useRef(false);
const loadItems = useCallback(async (reset = false) => {
if (loadingRef.current) return;
loadingRef.current = true;
const res = await axios.get('http://localhost:5000/items', {
params: { offset: reset ? 0 : offsetRef.current, limit, search }
});
if (reset) {
setItems(res.data);
offsetRef.current = limit;
} else {
setItems(prev => [...prev, ...res.data]);
offsetRef.current += limit;
}
loadingRef.current = false;
}, [search]);
useEffect(() => { loadItems(true); }, [loadItems]);
const handleSelect = (id) => {
setSelectedIds(prev =>
prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]
);
setItems(prev =>
prev.map(item => item.id === id ? { ...item, selected: !item.selected } : item)
);
};
const handleDragEnd = async (result) => {
if (!result.destination) return;
const reordered = Array.from(items);
const [moved] = reordered.splice(result.source.index, 1);
reordered.splice(result.destination.index, 0, moved);
setItems(reordered);
await axios.post('http://localhost:5000/update', {
movedId: moved.id,
sourceIndex: result.source.index,
destinationIndex: result.destination.index,
offset: offsetRef.current - items.length,
selectedIds
});
};
const handleScroll = (e) => {
const { scrollTop, scrollHeight, clientHeight } = e.target;
if (scrollHeight - scrollTop <= clientHeight + 5) {
loadItems();
}
};
const handleSearchChange = (e) => {
setSearch(e.target.value);
offsetRef.current = 0;
setItems([]);
loadItems(true);
};
return (
<div style={{ fontFamily: 'Arial, sans-serif', padding: '20px' }}>
<input
placeholder="Поиск"
value={search}
onChange={handleSearchChange}
style={{
marginBottom: '15px',
padding: '8px 12px',
width: '250px',
borderRadius: '8px',
border: '1px solid #ccc',
outline: 'none',
transition: 'box-shadow 0.2s',
}}
onFocus={e => e.target.style.boxShadow = '0 0 5px #1890ff'}
onBlur={e => e.target.style.boxShadow = 'none'}
/>
<div
onScroll={handleScroll}
style={{
height: '500px',
overflowY: 'auto',
border: '1px solid #ccc',
borderRadius: '8px',
padding: '10px',
background: '#fafafa'
}}
>
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId="list">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id.toString()} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
display: 'flex',
alignItems: 'center',
padding: '8px 12px',
marginBottom: '6px',
borderRadius: '6px',
border: '1px solid #eee',
background: item.selected ? '#e6f7ff' : snapshot.isDragging ? '#ffe58f' : 'white',
boxShadow: snapshot.isDragging ? '0 4px 8px rgba(0,0,0,0.1)' : 'none',
transition: 'background 0.2s, box-shadow 0.2s',
...provided.draggableProps.style
}}
>
<input
type="checkbox"
checked={item.selected || selectedIds.includes(item.id)}
onChange={() => handleSelect(item.id)}
style={{ marginRight: '12px', cursor: 'pointer' }}
/>
<span style={{ fontWeight: 500 }}>{item.id}</span>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
</div>
);
};
export default Table;