クエリー自動補完キーボードコントロール(with:react)
その位置決めは、以前の位置決めに関連付けられています.
リンク
今日のポジショニング内容は,タイトルのように,自動完了した検索語データにキーボードでアクセスして選択する機能である.
->前回の位置決め結果から開始します.
useRef
リンク
今日のポジショニング内容は,タイトルのように,自動完了した検索語データにキーボードでアクセスして選択する機能である.
->前回の位置決め結果から開始します.
useRef
まずuseref hooksを使います.
userefについて簡単に説明します.通常のJavaScriptではgetElementById、querySelectorなどのDOMセレクタ関数を使用してDOMを選択し、reactではuseref hookを使用してdomにアクセスできます.
userefの詳細については、リンクを参照してください.
では、なぜDomにアクセスしてキーボードを制御するのでしょうか.写真を見て
この画像は私たちが自動的に完成した検索語html形式です.
div->ul->liでアクセスする必要があります.私たちの自動完成キーワードに達することができます.
スキップコードは、以前の転送最終コードで見つけることができます.
userefの適用
function Header() {
...생략
const autoRef = useRef<HTMLUListElement>(null);
}
console.log(autoRef);
return (
...생략
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
)
ref値はstyled-componentと宣言されたulTagに渡されます.
コンソールも表示できます.
写真などの属性を確認できます.
私たちが見たい属性はタグのchildrenです.
childrenプロパティには、先に説明したli tagのリストがあります.
すなわち.refでサブ要素にアクセスするとdivタグをクリックせず、liタグの値にアクセスすれば終了します.
キーボードを使用した索引の選択 function Header() {
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
const [index,setIndex] = useState<number>(-1);
return (
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
)}
コードを見てみましょう.index変数の初期値が-1の点を深く理解する必要があります.
自動完了データが受信された場合、配列では最初のインデックス値が0で始まるため、-1値として指定します.
次に、isFocusというpropsをAutoSearchDataコンポーネントに渡し、キーボードでもキーワードhoverスタイルを自動的に完了するようにindex値とES 6 mapパラメータにインデックスを取得し、trueとfalseを返すことができます.
keydown関数の作成 const ArrowDown = "ArrowDown";
const ArrowUp = "ArrowUp";
const Escape = "Escape";
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown: //키보드 아래 키
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp: //키보드 위에 키
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape: // esc key를 눌렀을때,
setKeyItems([]);
setIndex(-1);
break;
}
}
}
return (
<Search
value={keyword}
onChange={onChangeData}
onKeyDown={handleKeyArrow}
/>
...생략
)
まず、keyが押されているためeventプロパティを使用する必要があります.
上矢印キー「ArrowDown」下矢印キー「ArrowUp」
つまり、e.key=="ArrowDown"エンクロージャは、ダウンキーを押したときに動作します.
e.key===「文字列」はオタワエラーを防止するために定数処理を提供します.
if (autoRef.current?.childElementCount === index + 1) setIndex(0); このセクションでは、最後のインデックスキーで下矢印キーを押すと、最初のインデックスキーに戻ります.
Ex:childElementCount->liタグの個数.
結果画面
最終コード import React, { useRef } from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
const SearchContainer = styled.div`
width: 400px;
height: 45px;
position: relative;
border: 0;
img {
position: absolute;
right: 10px;
top: 10px;
}
`;
const Search = styled.input`
border: 0;
padding-left: 10px;
background-color: #eaeaea;
width: 100%;
height: 100%;
outline: none;
`;
const AutoSearchContainer = styled.div`
z-index: 3;
height: 50vh;
width: 400px;
background-color: #fff;
position: absolute;
top: 45px;
border: 2px solid;
padding: 15px;
`;
const AutoSearchWrap = styled.ul`
`;
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
interface autoDatas {
city: string;
growth_from_2000_to_2013: string;
latitude:number;
longitude:number;
population:string;
rank:string;
state:string;
}
function Header() {
const [keyword, setKeyword] = useState<string>("");
const [index,setIndex] = useState<number>(-1);
const [keyItems, setKeyItems] = useState<autoDatas[]>([]);
const autoRef = useRef<HTMLUListElement>(null);
const onChangeData = (e:React.FormEvent<HTMLInputElement>) => {
setKeyword(e.currentTarget.value);
};
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown:
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp:
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape:
setKeyItems([]);
setIndex(-1);
break;
}
}
}
const fetchData = () =>{
return fetch(
`https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json`
)
.then((res) => res.json())
.then((data) => data.slice(0,100))
}
interface ICity {
includes(data:string): boolean;
city?: any;
}
const updateData = async() => {
const res = await fetchData();
let b = res.filter((list: ICity) => list.city.includes(keyword) === true)
.slice(0,10);
// console.log(b);
setKeyItems(b);
}
useEffect(() => {
updateData();
},[keyword])
return (
<SearchContainer>
<Search value={keyword} onChange={onChangeData} onKeyDown={handleKeyArrow}/>
<img src="assets/imgs/search.svg" alt="searchIcon" />
{keyItems.length > 0 && keyword && (
<AutoSearchContainer>
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
>
<a href="#">{search.city}</a>
<img src="assets/imgs/north_west.svg" alt="arrowIcon" />
</AutoSearchData>
))}
</AutoSearchWrap>
</AutoSearchContainer>
)}
</SearchContainer>
);
}
export default Header;
ありがとうございます.
Reference
この問題について(クエリー自動補完キーボードコントロール(with:react)), 我々は、より多くの情報をここで見つけました
https://velog.io/@gbwlxhd97/검색어-자동완성-키보드-컨트롤-withreact
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
function Header() {
...생략
const autoRef = useRef<HTMLUListElement>(null);
}
console.log(autoRef);
return (
...생략
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
)
function Header() {
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
const [index,setIndex] = useState<number>(-1);
return (
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
)}
コードを見てみましょう.index変数の初期値が-1の点を深く理解する必要があります.自動完了データが受信された場合、配列では最初のインデックス値が0で始まるため、-1値として指定します.
次に、isFocusというpropsをAutoSearchDataコンポーネントに渡し、キーボードでもキーワードhoverスタイルを自動的に完了するようにindex値とES 6 mapパラメータにインデックスを取得し、trueとfalseを返すことができます.
keydown関数の作成 const ArrowDown = "ArrowDown";
const ArrowUp = "ArrowUp";
const Escape = "Escape";
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown: //키보드 아래 키
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp: //키보드 위에 키
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape: // esc key를 눌렀을때,
setKeyItems([]);
setIndex(-1);
break;
}
}
}
return (
<Search
value={keyword}
onChange={onChangeData}
onKeyDown={handleKeyArrow}
/>
...생략
)
まず、keyが押されているためeventプロパティを使用する必要があります.
上矢印キー「ArrowDown」下矢印キー「ArrowUp」
つまり、e.key=="ArrowDown"エンクロージャは、ダウンキーを押したときに動作します.
e.key===「文字列」はオタワエラーを防止するために定数処理を提供します.
if (autoRef.current?.childElementCount === index + 1) setIndex(0); このセクションでは、最後のインデックスキーで下矢印キーを押すと、最初のインデックスキーに戻ります.
Ex:childElementCount->liタグの個数.
結果画面
最終コード import React, { useRef } from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
const SearchContainer = styled.div`
width: 400px;
height: 45px;
position: relative;
border: 0;
img {
position: absolute;
right: 10px;
top: 10px;
}
`;
const Search = styled.input`
border: 0;
padding-left: 10px;
background-color: #eaeaea;
width: 100%;
height: 100%;
outline: none;
`;
const AutoSearchContainer = styled.div`
z-index: 3;
height: 50vh;
width: 400px;
background-color: #fff;
position: absolute;
top: 45px;
border: 2px solid;
padding: 15px;
`;
const AutoSearchWrap = styled.ul`
`;
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
interface autoDatas {
city: string;
growth_from_2000_to_2013: string;
latitude:number;
longitude:number;
population:string;
rank:string;
state:string;
}
function Header() {
const [keyword, setKeyword] = useState<string>("");
const [index,setIndex] = useState<number>(-1);
const [keyItems, setKeyItems] = useState<autoDatas[]>([]);
const autoRef = useRef<HTMLUListElement>(null);
const onChangeData = (e:React.FormEvent<HTMLInputElement>) => {
setKeyword(e.currentTarget.value);
};
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown:
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp:
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape:
setKeyItems([]);
setIndex(-1);
break;
}
}
}
const fetchData = () =>{
return fetch(
`https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json`
)
.then((res) => res.json())
.then((data) => data.slice(0,100))
}
interface ICity {
includes(data:string): boolean;
city?: any;
}
const updateData = async() => {
const res = await fetchData();
let b = res.filter((list: ICity) => list.city.includes(keyword) === true)
.slice(0,10);
// console.log(b);
setKeyItems(b);
}
useEffect(() => {
updateData();
},[keyword])
return (
<SearchContainer>
<Search value={keyword} onChange={onChangeData} onKeyDown={handleKeyArrow}/>
<img src="assets/imgs/search.svg" alt="searchIcon" />
{keyItems.length > 0 && keyword && (
<AutoSearchContainer>
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
>
<a href="#">{search.city}</a>
<img src="assets/imgs/north_west.svg" alt="arrowIcon" />
</AutoSearchData>
))}
</AutoSearchWrap>
</AutoSearchContainer>
)}
</SearchContainer>
);
}
export default Header;
ありがとうございます.
Reference
この問題について(クエリー自動補完キーボードコントロール(with:react)), 我々は、より多くの情報をここで見つけました
https://velog.io/@gbwlxhd97/검색어-자동완성-키보드-컨트롤-withreact
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
const ArrowDown = "ArrowDown";
const ArrowUp = "ArrowUp";
const Escape = "Escape";
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown: //키보드 아래 키
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp: //키보드 위에 키
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape: // esc key를 눌렀을때,
setKeyItems([]);
setIndex(-1);
break;
}
}
}
return (
<Search
value={keyword}
onChange={onChangeData}
onKeyDown={handleKeyArrow}
/>
...생략
)
最終コード import React, { useRef } from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
const SearchContainer = styled.div`
width: 400px;
height: 45px;
position: relative;
border: 0;
img {
position: absolute;
right: 10px;
top: 10px;
}
`;
const Search = styled.input`
border: 0;
padding-left: 10px;
background-color: #eaeaea;
width: 100%;
height: 100%;
outline: none;
`;
const AutoSearchContainer = styled.div`
z-index: 3;
height: 50vh;
width: 400px;
background-color: #fff;
position: absolute;
top: 45px;
border: 2px solid;
padding: 15px;
`;
const AutoSearchWrap = styled.ul`
`;
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
interface autoDatas {
city: string;
growth_from_2000_to_2013: string;
latitude:number;
longitude:number;
population:string;
rank:string;
state:string;
}
function Header() {
const [keyword, setKeyword] = useState<string>("");
const [index,setIndex] = useState<number>(-1);
const [keyItems, setKeyItems] = useState<autoDatas[]>([]);
const autoRef = useRef<HTMLUListElement>(null);
const onChangeData = (e:React.FormEvent<HTMLInputElement>) => {
setKeyword(e.currentTarget.value);
};
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown:
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp:
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape:
setKeyItems([]);
setIndex(-1);
break;
}
}
}
const fetchData = () =>{
return fetch(
`https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json`
)
.then((res) => res.json())
.then((data) => data.slice(0,100))
}
interface ICity {
includes(data:string): boolean;
city?: any;
}
const updateData = async() => {
const res = await fetchData();
let b = res.filter((list: ICity) => list.city.includes(keyword) === true)
.slice(0,10);
// console.log(b);
setKeyItems(b);
}
useEffect(() => {
updateData();
},[keyword])
return (
<SearchContainer>
<Search value={keyword} onChange={onChangeData} onKeyDown={handleKeyArrow}/>
<img src="assets/imgs/search.svg" alt="searchIcon" />
{keyItems.length > 0 && keyword && (
<AutoSearchContainer>
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
>
<a href="#">{search.city}</a>
<img src="assets/imgs/north_west.svg" alt="arrowIcon" />
</AutoSearchData>
))}
</AutoSearchWrap>
</AutoSearchContainer>
)}
</SearchContainer>
);
}
export default Header;
ありがとうございます.
Reference
この問題について(クエリー自動補完キーボードコントロール(with:react)), 我々は、より多くの情報をここで見つけました
https://velog.io/@gbwlxhd97/검색어-자동완성-키보드-컨트롤-withreact
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
import React, { useRef } from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
const SearchContainer = styled.div`
width: 400px;
height: 45px;
position: relative;
border: 0;
img {
position: absolute;
right: 10px;
top: 10px;
}
`;
const Search = styled.input`
border: 0;
padding-left: 10px;
background-color: #eaeaea;
width: 100%;
height: 100%;
outline: none;
`;
const AutoSearchContainer = styled.div`
z-index: 3;
height: 50vh;
width: 400px;
background-color: #fff;
position: absolute;
top: 45px;
border: 2px solid;
padding: 15px;
`;
const AutoSearchWrap = styled.ul`
`;
const AutoSearchData = styled.li<{isFocus?: boolean}>`
padding: 10px 8px;
width: 100%;
font-size: 14px;
font-weight: bold;
z-index: 4;
letter-spacing: 2px;
&:hover {
background-color: #edf5f5;
cursor: pointer;
}
background-color: ${props => props.isFocus? "#edf5f5" : "#fff"};
position: relative;
img {
position: absolute;
right: 5px;
width: 18px;
top: 50%;
transform: translateY(-50%);
}
`;
interface autoDatas {
city: string;
growth_from_2000_to_2013: string;
latitude:number;
longitude:number;
population:string;
rank:string;
state:string;
}
function Header() {
const [keyword, setKeyword] = useState<string>("");
const [index,setIndex] = useState<number>(-1);
const [keyItems, setKeyItems] = useState<autoDatas[]>([]);
const autoRef = useRef<HTMLUListElement>(null);
const onChangeData = (e:React.FormEvent<HTMLInputElement>) => {
setKeyword(e.currentTarget.value);
};
const handleKeyArrow = (e:React.KeyboardEvent) => {
if (keyItems.length > 0) {
switch (e.key) {
case ArrowDown:
setIndex(index + 1);
if (autoRef.current?.childElementCount === index + 1) setIndex(0);
break;
case ArrowUp:
setIndex(index - 1);
if (index <= 0) {
setKeyItems([]);
setIndex(-1);
}
break;
case Escape:
setKeyItems([]);
setIndex(-1);
break;
}
}
}
const fetchData = () =>{
return fetch(
`https://gist.githubusercontent.com/Miserlou/c5cd8364bf9b2420bb29/raw/2bf258763cdddd704f8ffd3ea9a3e81d25e2c6f6/cities.json`
)
.then((res) => res.json())
.then((data) => data.slice(0,100))
}
interface ICity {
includes(data:string): boolean;
city?: any;
}
const updateData = async() => {
const res = await fetchData();
let b = res.filter((list: ICity) => list.city.includes(keyword) === true)
.slice(0,10);
// console.log(b);
setKeyItems(b);
}
useEffect(() => {
updateData();
},[keyword])
return (
<SearchContainer>
<Search value={keyword} onChange={onChangeData} onKeyDown={handleKeyArrow}/>
<img src="assets/imgs/search.svg" alt="searchIcon" />
{keyItems.length > 0 && keyword && (
<AutoSearchContainer>
<AutoSearchWrap ref={autoRef}>
{keyItems.map((search, idx) => (
<AutoSearchData
isFocus={index === idx ? true : false}
key={search.city}
onClick={() => {
setKeyword(search.city);
}}
>
<a href="#">{search.city}</a>
<img src="assets/imgs/north_west.svg" alt="arrowIcon" />
</AutoSearchData>
))}
</AutoSearchWrap>
</AutoSearchContainer>
)}
</SearchContainer>
);
}
export default Header;
Reference
この問題について(クエリー自動補完キーボードコントロール(with:react)), 我々は、より多くの情報をここで見つけました https://velog.io/@gbwlxhd97/검색어-자동완성-키보드-컨트롤-withreactテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol