맞춤형 갈고리를 통해 자동 완성
본고는 ReactJS 맞춤형 갈고리를 사용하여 국가 검색 입력에 간단한 자동 완성을 사용하는 방법을 보여 준다.
사용자 인터페이스 구조
사용자가 국가 이름을 검색할 수 있도록 돕기 위한 입력이 있습니다.사용자의 입력에 따라 우리는 몇 가지 건의를 보여 주고 싶다.
검색 양식의 코드 구조와 스타일은 다음과 같습니다.
// src/autocomplete/index.js
import styled from 'styled-components';
import { ReactComponent as SearchIcon } from './search-icon.svg';
import countries from './countries';
const SearchForm = () => {
const handleSubmit = (e) => {
e.preventDefault();
};
return (
<div>
<Form
autoComplete="off" // disable the browser built-in autocomplete
onSubmit={handleSubmit}
>
<Container>
<Input/>
<SubmitButton>
<SearchIcon />
</SubmitButton>
</Container>
</Form>
</div>
);
};
const Container = styled.div`
position: relative;
`;
const List = styled.div`
position: absolute;
top: 100%;
left: 0;
right: 0;
height: 40vh;
background-color: #293241;
border-radius: 0 0 5px 5px;
overflow-y: scroll;
`;
const Item = styled.div`
border-left: 3px solid ${({ active }) => (active ? 'blue' : 'initial')};
background-color: ${({ active }) => (active ? 'gray' : 'initial')};
padding: 0 15px;
color: ${({ active }) => (active ? 'white' : '#f2e9e4')};
cursor: pointer;
&:hover {
background-color: gray;
}
`;
const Input = styled.input`
background-color: #293241;
color: #f2e9e4;
border: none;
width: 400px;
padding: 15px 15px;
border-radius: 5px 0 0 0;
&:focus {
outline: none;
}
`;
const Match = styled.strong`
color: #c9ada7;
`;
const Form = styled.form`
width: 100vw;
height: 100vh;
background-color: #4a4e69;
padding-top: 10%;
display: flex;
align-items: flex-start;
justify-content: center;
`;
const SubmitButton = styled.button`
outline: none;
background-color: #293241;
padding: 15px 20px;
border: none;
color: #f2e9e4;
border-radius: 0 5px 0 0;
&:focus {
outline: none;
}
`;
export default SearchForm;
자동 완성 갈고리 사용
useAutocomplete
는 논리를 자동으로 완성하는 사용자 정의 갈고리입니다.우선, 검색 입력 값의 변화를 처리합니다.// src/autocomplete/useAutocomplete.js
import { useState } from 'react';
const INITIAL_STATE = {
value: '',
};
const useAutocomplete = (initialState = INITIAL_STATE) => {
const [{ value }, setState] = useState(initialState);
const handleValueChange = (newValue) => {
setState((s) => ({
...s,
value: newValue,
}));
};
return {
value,
handleValueChange,
};
};
export default useAutocomplete;
이제 검색 입력에 사용할 항목:// src/autocomplete/index.js
//...
import useAutocomplete from './useAutocomplete';
const SearchForm = () => {
const { value, handleValueChange } = useAutocomplete();
//...
return (
<div>
//...
<Input
value={value}
onChange={(e) => handleValueChange(e.target.value)}
/>
//...
</div>
);
};
그 다음으로 우리는 국가 이름을 필터한다.우리는 국가 목록을 handleValueChange
함수의 매개 변수로 얻었다.필터 결과, 즉 갈고리 상태에 저장하는 것이 좋습니다.// src/autocomplete/useAutocomplete.js
// ...
const INITIAL_STATE = {
// ...
suggestions: [], // contains autocomplete suggestions
};
const useAutocomplete = (initialState = INITIAL_STATE) => {
const [{ value }, setState] = useState(initialState);
const handleValueChange = (newValue, items) => {
setState((s) => ({
...s,
value: newValue,
suggestions: items
.filter((item) => {
/*
if the letters typed by the user match the beginning
of the item we keep it
*/
const match = item.substr(0, newValue.length);
return match && match.toLowerCase() === newValue.toLowerCase();
})
.slice(0, 13), // limits the suggestion to 13 items
}));
};
return {
// ...
suggestions, // exports the suggestions
};
};
// ...
사용자가 입력할 때, 우리는 일치하는 부분의 스타일이 모든 제안된 나머지 부분과 다르기를 희망합니다.이를 위해 제안된 데이터 구조 변경은 다음과 같습니다.// src/autocomplete/useAutocomplete.js
// ...
const handleValueChange = (newValue, items) => {
setState((s) => ({
// ...
suggestions: items
.filter((item) => {
// ...
})
.map((item) => ({ rest: item.substr(newValue.length), itemValue: item }))
.slice(0, 13),
// ...
handleValueChange
의 호출자는 사용자 정의 선별 함수를 제공할 수 있습니다.개별 함수에서 현재 필터 로직을 추출하고 사용자 정의 필터 함수를 옵션으로 적용합니다.// src/autocomplete/useAutocomplete.js
// ...
const defaultFilter = (inputValue, items) =>
items
.filter((item) => {
const match = item.substr(0, inputValue.length);
return match && match.toLowerCase() === inputValue.toLowerCase();
})
.map((item) => ({
rest: item.substr(inputValue.length),
itemValue: item,
}))
.slice(0, 13);
const useAutocomplete = () => {
// ...
const handleValueChange = (newValue, items, { customFilter } = {}) => {
// uses customFilter if defined
const filter = customFilter ?? defaultFilter;
setState((s) => ({
// ...
suggestions: filter(newValue, items),
}));
};
//...
이제 다음과 같은 권장 사항을 사용자에게 제시할 수 있습니다.// src/autocomplete/index.js
// ...
const SearchForm = () => {
const { value, handleValueChange, suggestions } = useAutocomplete()
const hasSuggestions = !(Array.isArray(suggestions) && !suggestions.length);
// ...
<Input
value={value}
onChange={(e) => handleValueChange(e.target.value, data)}
/>
<SubmitButton>
<SearchIcon />
</SubmitButton>
{hasSuggestions && (
<List>
{suggestions.map(({ rest, itemValue }, i) => (
<Item key={itemValue}>
<Match>{value}</Match>
{rest}
</Item>
))}
</List>
)}
// ...
다음 단계에서 우리가 해야 할 일은 그것을 눌렀을 때 그 중 하나를 선택하는 것이다.
select
갈고리에 useAutocomplete
함수를 만듭니다.// src/autocomplete/useAutocomplete.js
// ...
const useAutocomplete = (initialState = INITIAL_STATE) => {
// ...
const select = (value) => setState({ ...INITIAL_STATE, value });
return {
// ...
select,
};
};
// ...
다음은 각 제안된 항목에 대한 클릭 이벤트를 관리합니다.// src/autocomplete/index.js
// ...
const SearchForm = () => {
// imports the select function
const { ..., select } = useAutocomplete();
// ...
{suggestions.map(({ rest, itemValue }, i) => (
<Item key={itemValue} onClick={() => select(itemValue)}>
// ...
자동 완성 입력은 일반적으로 위쪽과 아래쪽 화살표 키를 사용하여 제안 항목을 탐색할 수 있습니다.또한 [amp]lt;Enter[amp]gt;키를 눌러 권장 사항을 선택할 수도 있습니다.우리는 이 모든 기능을 검색 입력에 추가할 것이다.제안 간에 이동할 때 현재 갈고리 상태에 있는 권장 사항을 추적해야 합니다.
// src/autocomplete/useAutocomplete.js
const INITIAL_STATE = {
// ...
currentFocus: null,
};
처음에 currentFocus
는 null
로 설정되었습니다.초점이 전혀 없다는 뜻이다.사용자가 입력을 시작할 때, 우리는 currentFocus
-1
를 원한다.이런 상황에서 중점은 입력 자체다.왜 우리는 텍스트 입력을 초점을 맞출 수 있는 요소로 간주해야 합니까?이해하기 위해서 구체적인 사례를 생각해 봅시다.사용자가 타자를 시작하고 맨 밑에 있는 제안이 사용자가 찾고 있는 내용과 일치한다고 가정하십시오.사용자가 위쪽 화살표 키를 눌렀을 때, 우리는 초점이 마지막 제안으로 바로 넘어가기를 희망합니다.
null
와 -1
를 제외하고currentFocus
는 주동적으로 건의한 색인을 가지고 있다.이 점을 고려하여 다음과 같이 함수
handleValueChange
가 업데이트됩니다.// src/autocomplete/useAutocomplete.js
// ...
const useAutocomplete = (initialState = INITIAL_STATE) => {
// ...
const handleValueChange = (newValue, items) => {
setState((s) => ({
...s,
currentFocus: -1, // the focus is on the search input at the beginning
value: newValue,
// ...
그런 다음 세 가지 유형의 키 닫기 이벤트를 처리합니다.// src/autocomplete/useAutocomplete.js
// ...
const useAutocomplete = (initialState = INITIAL_STATE) => {
const [{ value, suggestions, currentFocus }, setState] = useState(initialState);
// ...
const handleKeyDown = ({ key }) => {
switch (key) {
case 'ArrowDown':
setState((s) => ({
...s,
currentFocus:
s.currentFocus === s.suggestions.length - 1
? 0
: s.currentFocus + 1,
}));
break;
case 'ArrowUp':
setState((s) => ({
...s,
currentFocus:
s.currentFocus === 0 || s.currentFocus === -1
? s.suggestions.length - 1
: s.currentFocus - 1,
}));
break;
case 'Enter':
if (currentFocus !== null && currentFocus !== -1) {
select(suggestions[currentFocus].itemValue);
}
break;
default:
break;
}
};
return {
// ...
handleKeyDown,
currentFocus,
};
};
// ...
ArrowDown
사건에 대해 우리는 활동 건의가 맨 밑에 있는지 검사한다: s.currentFocus === s.result.length - 1
.만약 이런 상황이라면, 우리는 색인의 맨 끝 제안 0
으로 이동하고, 그렇지 않으면 다음 제안 s.currentFocus + 1
으로 이동합니다.ArrowUp
사건에 대해 과정은 유사하지만 반대이다.만약 현재의 중점이 첫 번째 건의(s.currentFocus === 0
)나 입력 자체(s.currentFocus === -1
))라면 우리는 최하층s.suggestions.length - 1
부터 시작하기를 희망한다.만약 없다면, 우리는 앞의 건의를 보겠다(s.currentFocus - 1
.다음은 현재 이벤트에 대한 권장 값
Enter
을 선택하여 이벤트를 처리합니다.다음 항목은 검색 입력에 다음 키 처리 프로그램을 추가합니다.
// src/autocomplete/index.js
<Input
onKeyDown={handleKeyDown}
// ...
/>
스타일링 구성 요소
select(suggestions[currentFocus].itemValue)
의 active
속성에 따라 사전 예방적으로 권장되는 디스플레이 방법은 다음과 같습니다.// src/autocomplete/index.js
//...
{result.map(({ match, rest, value }, i) => (
<Item
active={i === currentFocus}
// ...
>
// ...
우리의 간단한 자동 완성 입력은 이미 완성되었다.The complete code can be found in this repo
결론
Item
갈고리는 자동 완성 논리를 추상화했다.그것은 끊임없이 변화하는 입력 값을 제어한 후에 몇 가지 건의를 제기했다.이러한 권장 사항은 기본 필터 또는 사용자 정의 기능을 사용하여 생성됩니다.이 밖에useAutocomplete는 일부 버튼 닫기 이벤트를 처리했습니다.그래서 우리는 깨끗한
useAutocomplete
구성 요소를 가지고 코드의 중용성을 얻었다.읽어주셔서 감사합니다!
Reference
이 문제에 관하여(맞춤형 갈고리를 통해 자동 완성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/nazifbara/autocomplete-through-reactjs-custom-hook-2odo텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)