본문 바로가기
웹/React

[React] 검색텍스트 입력 후 버튼 누르면 검색되게 하기, react에서 입력값 가져오기

by ohojee 2023. 9. 21.

openapi를 이용해 검색 기능을 구현하려고 했다. html과 css 요소는 아래와 같다.

return (
	<>
        <SearchBox>
            <SearchInput placeholder="책 이름을 입력해주세요."/>
            <SearchBtn className='butn' size="54"/>
        </SearchBox>
	</>
)

const SearchBox = styled.div`
    display: flex;
    grid-area: searchBox;
    width: 781px;
    height: 93px;
    border-radius: 50px;
    border: 4px solid #4659A9;
    align-items: center;
    margin: 60px;
`;

const SearchInput = styled.input`
    border: transparent;
    outline: none;
    margin-left:40px;
    width: 100%;
    height: 90%;
    font-size: 35px;
`;

const SearchBtn = styled(IoSearch)`
    fill: #4659A9;
    margin: 0 25px;
`;

저 input 창에 검색텍스트를 넣은 후 돋보기 버튼을 누르면 openapi에 input텍스트를 넣어 api요청을 보내려고 했다.

const [searchText, setSearchText] = useState('');
const handleSearchText = (e) => {
    const currentText = e.currentTarget.value;
    setSearchText(currentText)
}
return (
    <>
    <SearchBox>
        <SearchInput placeholder="책 이름을 입력해주세요."/>
        <SearchBtn className='butn' size="54" onClick={handleSearchText}/>
    </SearchBox>
    </>
)

그래서 가장 먼저 만들었던 것은 이 코드. handleSearchText를 onClick 요소에 넣으려고 했다. 처음에는 searchBtn에 onClick으로 넣었다.

그 결과는 undefined. 당연함. currrentTarget은 저 돋보기 버튼이니 안에 있는 value가 없는 것이다. 
 
그러던 중 target과 currrentTarget의 차이를 찾았다. 위의 코드와는 onClick이 걸린 요소가 다르다.

<SearchBox className='box' onClick={handleSearchText}>
    <SearchInput placeholder="책 이름을 입력해주세요."/>
    <SearchBtn className='butn' size="54" />
</SearchBox>

currrentTarget은 앞서 말한대로 onClick요소가 걸려있는 요소를 말한다. 여기서는 SearchBox이다. 그리고 target은 직접 클릭된 요소, 즉 SearchBtn이 나온다.
근데 onClick을 박스에 걸어두니 input을 입력하려 누를 때에도 이벤트가 발생했다. 그래서 SearchBtn으로 onClick 이벤트를 옮겼다. 그렇다면 형제요소에 있는 텍스트를 가져올 수 있는 방법을 찾아야한다. 
처음에는 id값으로 SearchInput을 찾으려했다.

<SearchBox>
    <SearchInput id='searchInput' placeholder="책 이름을 입력해주세요."/>
    <SearchBtn className='butn' size="54" onClick={handleSearchText}/>
</SearchBox>
const currentText = e.currentTarget.querySelector('#searchInput');

그래서 이런식으로 작성했다. 하지만 왜인지 null로 뜬다. 
class name으로 설정한 후 .querySelector('.searchInput')을 해도 null로 떴다. 찾아보니 html요소보다 js가 먼저 실행되서 그렇다고 한다. 대부분 <script>로 js를 실행해서 <body>뒤에 <script>를 넣으면 된다고 조언해주었다. ref를 쓰면 된다고는 하던데 나중에 리팩토링 할 때 다시 찾아봐야겠다. 

const currentText = e.currentTarget.parentNode.children[0].value;
setSearchText(currentText)

const result = await axios.get(`ttb/api/ItemSearch.aspx?ttbkey=${process.env.REACT_APP_TTBKEY}&Query=${searchText}
...

나는 이렇게 btn의 부모노드(searchBox)의 자식 중 첫번째(searchInput)의 value를 가져오는 방식으로 작성했다. 너무 복잡해보이긴한다. 그리고 찾은 값을 set해주었다. 그 후 api요청에 ${searchText}를 넣어주었다.

그러면 이렇게 검색이 된다!
 
참고 자료
https://life-of-erin.tistory.com/32
https://mchch.tistory.com/204
https://okky.kr/questions/655641

댓글