как правильно реализовать поиск в массиве объектов react
Мне необходимо реализовать поиск в массиве объектов по тексту объекта. Я уже пытался реализовать через .find, но он, как и положено выдаёт первое. Снизу преведен вариант с рабочим поиском, но он- зараза, из-за filter получается одноразовым) Я только начал изучение react(знаю только useState) и не могу понять, как сделать, чтобы искодный массив не изменялсяю Сейчас пробую вариант с копией массива, но получается не так как надо
function getId(length = 16) {
let chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
let res = "";
for (let i = 0; i < length; i++) {
res += chars[Math.floor(Math.random() * chars.length)];
}
return res;
}
const Notebook = () => {
const initNotes = [
{
id: getId(),
name: "Note1",
text: "text1",
isEdit: false,
},
{
id: getId(),
name: "Note2",
text: "text2",
isEdit: false,
},
{
id: getId(),
name: "Note3",
text: "text3",
isEdit: false,
},
];
const [notes, setNotes] = useState(initNotes);
function search(event) {
setNotes(
notes.filter((note) => {
if (note.text.search(event.target.value) !== -1) {
return note;
}
})
);
}
const result = notes.map((prod) => {
return <p type='text' key={prod.id}>{prod.text}</p>;
})
return (
<>
<input onChange={(event)=>search(event} />
{result}
</>
);
};
Ответы (2 шт):
Для реализации фильтрации массива целесообразно использовать метод .filter и результат сортировки сохранять в отдельной переменной состояния.
Если поисковая строка оказывается пуста, то подставляем в переменную состояния исходный массив
const App = () => {
// Переменная для отфильтрованного массива и его отображения
const [notes, setNotes] = useState([ ...initNotes ]);
// Переменная для сохранения введенного значения input
const [searchString, setSearchString] = useState('');
function search(event) {
// Сохраняем введеное значение
setSearchString(event.target.value);
// Сохраняем резальтат фильтрации
setNotes(
event.target.value // Если строка не пустая, фильтруем
? initNotes.filter(note => note.text.search(event.target.value) !== -1)
: [ ...initNotes ] // Если строка пустая, подставляем исходный массив
);
}
return (
<div>
<input onChange={search} value={searchString} />
{notes.map(prod => <p type='text' key={prod.id}>{prod.text}</p>)}
</div>
)
}
// Исходный массив
const initNotes = [
{
id: 1,
name: "Note1",
text: "text1",
isEdit: false,
},
{
id: 2,
name: "Note2",
text: "text2",
isEdit: false,
},
{
id: 3,
name: "Note3",
text: "text3",
isEdit: false,
},
];
Мне необходимо реализовать поиск в массиве объектов по тексту объекта.
Такое можно реализовать, например, вот так...
//
function Itm({obj}) {
return <li>
{obj.text}
</li>
}
//
function List({fnd}) {
const [arr, setArr] = React.useState(data())
const fn = o => o.text.includes(fnd)
return <ul>
{arr.filter(fn).map(o => <Itm key={o.id} obj={o} />)}
</ul>
}
//
function Fnd({set}) {
const [val, setVal] = React.useState('')
const r = React.useRef()
React.useEffect(_ => _ => r.current && removeTimeout(r.current))
const act = e => {
const v = e.target.value
setVal(v)
if (r.current) removeTimeout(r.current)
setTimeout(_ => set(v), 200)
}
return <label>
<span>Поиск </span>
<input onChange={act} value={val} />
</label>
}
//
function App() {
const [fnd, setFnd] = React.useState('')
return <main>
<Fnd set={setFnd} />
<List fnd={fnd} />
</main>
}
const domContainer = document.querySelector('#like_button_container');
const root = ReactDOM.createRoot(domContainer);
root.render(<App />);
//
function data() {
return [
{
id: getId(),
name: "Note1",
text: "text1",
isEdit: false,
},
{
id: getId(),
name: "Note2",
text: "text2",
isEdit: false,
},
{
id: getId(),
name: "Note3",
text: "text3",
isEdit: false,
},
]
}
//
function getId(length = 16) {
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
let res = "";
for (let i = 0; i < length; i++) {
res += chars[Math.floor(Math.random() * chars.length)];
}
return res;
}
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<div id="like_button_container"></div>