FrontEnd/기능구현
서치박스 (SearchBox - React)
3일마다 작심3일
2021. 12. 24. 08:16
서치박스란?
서치박스는 인풋창 클릭 시 dropdown으로 아이템이 리스트형태로 나오며
input에 타이핑을하여 아이템을 쉽게 찾을 수 있게 만들어주는 기법(?) 이다.
sarch.test.js
describe("show Test", () => {
it("should show first", () => {
const datas = ["first", "second", "third", "four", "five"];
const inputWord = "first";
const expected = ["first"];
expect(searchWords(datas, inputWord)).toEqual(expected);
});
it("should show firstWords f", () => {
const datas = ["first", "second", "third", "four", "five"];
const inputWord = "f";
const expected = ["first", "four", "five"];
expect(searchWords(datas, inputWord)).toEqual(expected);
});
it("should show firstWords e", () => {
const datas = ["first", "second", "third", "four", "five"];
const inputWord = "s";
const expected = ["second"];
expect(searchWords(datas, inputWord)).toEqual(expected);
});
const searchWords = (datas, inputWord) => {
return datas.filter((word) => !word.search(inputWord));
};
});
해당 코드는 search에 필요한 테스트들입니다.
첫번째 글자가 입력한 값인 inputWord와 매칭되는 것을 filter함수를 이용해 배열을 다시 만들어주는 방식으로 진행했습니다.
PSearch.js
import React, { useState } from 'react'
import Search from '../components/Search';
const PSearch = () => {
const initialDatas = require("../json/SearchDatas.json");
const [ input, setInput ] = useState('');
const [ datas, setDatas ] = useState(initialDatas);
const onChange = (e) => {
const searchWords = (datas, inputWord) => {
return datas.filter((word) => !word.search(inputWord));
};
setInput(e.target.value);
setDatas(searchWords(initialDatas, e.target.value))
}
return (
<Search datas={datas} input={input} onChange={onChange}/>
)
}
export default PSearch
우선 보여줄 데이터인 initialDatas를 받아주고
onChange함수를 이용해 input에 값이 들어올때마다 filter함수와 테스트에 사용했던 함수를 그대로 를 사용하여 datas를 set해줍니다.
후에 컴포넌트인 Search에 datas와 input, onChange함수를 props로 넘겨줍니다.
Search.js
import React, { useState } from "react";
import styled from "styled-components";
const Container = styled.div`
width: 25rem;
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
padding: 1rem 2rem;
border: 1px solid black;
}
`;
const StyleInput = styled.input`
width: 100%;
height: 3rem;
padding: 0;
margin: 0;
position: relative;
box-sizing: border-box;
`;
const DataLists = styled.div`
${({ visiable }) => {
return {
display: visiable === false && "none"
}
}}
width: 100%;
height: 17rem;
overflow-y: scroll;
position: "absolute";
top: 0;
`;
const Search = ({ datas, input, onChange }) => {
const [ visiable, setVisiable ] = useState(false);
return (
<Container>
<StyleInput onClick={() => setVisiable(!visiable)} value={input} onChange={onChange} />
<DataLists visiable={visiable}>
<ul>
{datas.map((data, index) => (
<li key={`${data}_${index}`}>{data}</li>
))}
</ul>
</DataLists>
</Container>
);
};
export default Search;
코드가 길어보인다면 그것은 스타일드 컴포넌트때문입니다.
아무튼!
visiable을 상태로 관리하여 아이템이 나오는것을 관리해줍니다.
그리고 Input을 relative로 설정하고 DataLists를 absoulte로 설정한 후 top: 0 을 설정해주면 input에 DataLists가 착! 달라붙어 드롭다운효과를 낼 수 있습니다.
이제 DataLists에는 PSearch에 정의되어있던 onChange에의해 datas에는 제가 입력한 input값에 대한 data만 남아있을테니 map을 통해 datas를 통으로 렌더해주면 끝! 입니다!