ReactJS - 두 어레이의 일치하는 ID를 비교/필터링하고 결과를 이중 검색 기능에 사용하는 방법
내 앱에 이중 검색 기능이 있었으면 좋겠어.한 번 검색하면 제목별로 책을 걸러낸다.다른 한편, 장르별로 책을 여과한다.두 검색 필터는 함께 작동해야 한다(검색어가제공된 경우 제목 및 장르로 필터링해야 함).
하지만 장르 검색 필터 적용이 어려워.
** 참고**: 생성 시 각 장르 태그에 동일하게 할당됨id
딱 붙어있는 책처럼 말이야이런 식으로, 나는 검색되고 있는 장르와 관련된 모든 책을 끌어 올릴 수 있다.
개체:
book = { id: "id", title: "title", author: "author"}
genre = { id: "id", label: "label" }
상위 구성요소
export default function Books() {
const [books, setBooks] = useState([])
const [searchTitle, setSearchTitle] = useState("")
const [genres, setGenres] = useState([])
const [searchGenre, setSearchGenre] = useState("")
useEffect(() => {
fetch(`https://www.someapi.com/books`)
.then(r => r.json())
.then(setBooks)
}, [])
function handleAllGenres(val){
setGenres([...genres, val])
}
const filterGenres = genres.filter(genre => {
return genre.label.toLowerCase().includes(searchGenre.toLowerCase())
})
const filterBooks = books.filter(book => {
return book.title.toLowerCase().includes(searchTitle.toLowerCase())
})
const filterBookGenres = filterBooks.filter(book => {
if (searchGenres.length > 0) {
return filterGenres.some(genre => book.id === genre.id)
} else {
return books
}
})
const book = filterBookGenres.map(book => {
return (
<Book
key={book.id}
book={book}
genres={genres}
onAddGenre={handleAllGenres}
/>
)
})
return (
<div className="main-container">
<SearchTitle
searchTitle={searchTitle}
onSearchTitle={setSearchTitle}
/>
<SearchGenre
searchGenre={searchGenre}
onSearchGenre={setSearchGenre}
/>
{book}
</div>
);
}
하위 구성 요소:
export default function Book({ book, onAddGenre })
const [genreTags, setGenreTags] = useState([])
function handleAddGenre(e) {
const val = {
id: book.id,
label: e.target.value,
}
if (e.key === 'Enter' && val) {
if (genreTags.find(genre => genre.toLowerCase() === val.toLowerCase())) {
return
}
setGenreTags([...genreTags, val])
onAddGenre(val)
e.target.value = ""
}
}
return (
<div className="book-div">
<p>{title}</p>
<p>Written By: {author}</p>
</div>
<div className="tag-div">
<ul>
{ genreTags && genreTags.map(tag => {
return <li key={uuid()}> {tag.label} </li>
})}
</ul>
</div>
<input
type="text"
placeholder="Add a genre"
onKeyDown={handleAddGenre}
/>
);
}
구성 요소 검색:
export default function SearchTitle({ searchTitle, onSearchTitle }) {
return (
<div className="search">
<input
id="name-input"
placeholder="Search by title"
value={search}
onChange={e => onSearch(e.target.value)}
/>
</div>
);
}
export default function SearchGenre({ searchGenre, onSearchGenre }) {
return (
<div className="search">
<input
id="tag-input"
placeholder="Search by genre"
value={searchGenre}
onChange={e => onSearchTag(e.target.value)}
/>
</div>
)
}
업데이트: 검색 기능이 이제 작동하지만 두 검색 기능 중 하나를 사용하여 재생한 후 태그가 사라지는 것을 발견.예를 들어, 검색 값을 입력하고 책 목록을 필터링한 다음 검색어를 삭제하면 태그가 사라진다.내 생각엔 책이 다시 리렌더구나.
이 리렌더를 방지하거나 내 검색 기능을 가지고 놀다가 태그가 사라지는 것을 방지할 수 있는 방법이 있는가?
모든 도움은 감사했다.고마워!
OnClick 핸들러 내부를 볼 수 없기 때문에(다른 구성 요소에 있음(다른 구성 요소에 있음).나는 즉시 가능한 이슈 하나를 본다. (이상하게도, 당신이 장르를 타이틀 검색이 아닌 이슈라고 말한 것을 고려하면, 이상하다.인filterBooks
당신은 가지고 있다book => { return title.toLowerCase()...
, 그러나 그것은 그래야 한다.book => { return book.title.toLowerCase()...
또한, 이 코드 샘플에서는 설정하지 않고 있으며setGenres
. 는genres
비어있는 상태?
편집
이 리렌더를 방지하거나 내 검색 기능을 가지고 장난친 후 태그가 사라지지 않도록 하는 방법이 있는가?
예, 페이지를 새로 고치거나 마운트 해제하고 다시 마운트할 때까지 사용할 수 있는 해결 방법이 있습니다,Books
구성 요소개체는 변이 가능한 데이터 구조이므로 새 키("태그")를 추가하도록 개체를 변이할 수 있다.이런 것들은 비록 그것이 지속된다고 해도 계속될 것이다.Book
객체 분리 및 재장착우리는 이 일을 할 수 있다.handleAddGenre
에Book.js
다음과 같다:
function handleAddGenre(e) {
const val = {
id: book.id,
label: e.target.value
};
if (e.key === "Enter" && val) {
if (
/**
* Note that I made a small change here,
* adding 'labels' before the two toLowerCase methods
*/
genreTags.find(
(genre) => genre.label.toLowerCase() === val.label.toLowerCase()
)
) {
return;
}
/**
* we mutate the book object here.
* This will persist until we reset the books state,
* so searching doesn't make it disappear.
*/
book.tags = book.tags ? [...book.tags, val] : [val];
setGenreTags([...genreTags, val]);
onAddGenre(val);
e.target.value = "";
}
}
그러면, 우리는 책의 새 것을 통해 반복되어야 하기 때문에 그에 따라 렌더만 바꾸면 된다.tag
새 레이블을 모두 찾을 수 있는 키
<ul>
{book.tags &&
book.tags.map((tag) => {
return <li key={uuid()}> {tag.label} </li>;
})}
</ul>
이것 좀 봐.
import { useState } from "react";
import { Button, makeStyles } from "@material-ui/core";
import "./styles.css";
const genreList = [
{
id: 0,
label: "horror",
type: "fiction",
desc: "these creepy crawler stories will leave you shaking in your boots!"
},
{
id: 1,
label: "action",
type: "fiction",
desc: "a fun, colorful adventure awaits!"
},
{
id: 2,
label: "history",
type: "non-fiction",
desc: "A blast from the past!"
}
];
const bookList = [
{
id: 0,
title: "My First Book",
author: "Mint",
genreId: 2
},
{
id: 1,
title: "My Second Book",
author: "James Bond",
genreId: 1
},
{
id: 2,
title: "Here's the Third!",
author: "Batman",
genreId: 1
},
{
id: 3,
title: "The Holy Fourth Empire",
author: "John Snow",
genreId: 0
},
{
id: 4,
title: "Remember Remember the Fifth of November!",
autorh: "V",
genreId: 0
}
];
const useStyles = makeStyles({
root: {
flex: 1,
display: "flex",
flexDirection: "column"
},
header: {
paddingBottom: "10px"
},
bookList: {
height: "100px"
}
});
export default function App() {
const classes = useStyles();
const [genres, setGenres] = useState(genreList);
const [books, setBooks] = useState(bookList);
const [isSelected, setIsSelected] = useState(null);
return (
<div className={classes.root}>
<div className={classes.header}>
{isSelected !== null ? (
<h4>{genres[isSelected].label} Movies</h4>
) : (
<h4>All Movies</h4>
)}
</div>
<div className={classes.bookList}>
{isSelected === null
? books.map((book) => <p>{book.title}</p>)
: books
.filter((book) => book.genreId === isSelected)
.map((book) => <p>{book.title}</p>)}
</div>
<div className={classes.buttons}>
<Button onClick={() => setIsSelected(0)}>Horror</Button>
<Button onClick={() => setIsSelected(1)}>Action</Button>
<Button onClick={() => setIsSelected(2)}>History</Button>
<Button onClick={() => setIsSelected(null)}>All</Button>
</div>
</div>
);
}
'IT이야기' 카테고리의 다른 글
vue.js 단일 파일 구성 요소를 백그라운드에서 로드하는 방법 (0) | 2022.03.15 |
---|---|
MD 크기의 장치에 대해서만 요소 표시 (0) | 2022.03.15 |
각도 사용자 지정 오류 처리기가 약속에서 오류 유형을 가져오지 않음 (0) | 2022.03.14 |
애니메이션: ReactiveNativeBase 입력의 "NativeDriver"가 지정되지 않음 (0) | 2022.03.14 |
라우터 변경 url 응답은 하지만 보기 없음 (0) | 2022.03.14 |