무작위로 저장된 데이터를 알파벳 순으로 정렬해 렌더링해주는 버튼을 만들어 보았따
[
{"id": 0,"name": "Kwon"},
{"id": 1,"name": "Yoon"},
{"id": 2,"name": "Kim"},
{"id":3, "name":"ASH ISLAND", "kor_name":"애쉬 아일랜드","img":"https://user-images.githubusercontent.com/86250281/155518228-979a54ed-8ece-4ed1-9ea5-f121b5f0a49e.png"},
{"id":4, "name":"BLOO", "kor_name":"블루", "img":"https://user-images.githubusercontent.com/86250281/155535571-24040887-e0c4-40c7-8138-29b323c4533d.png"},
{"id":5, "name":"BEENZINO", "kor_name":"빈지노", "img":"https://user-images.githubusercontent.com/86250281/155535749-4a3b10c0-4b1a-4a4d-bc97-5096d2962a87.png"},
{"id":6, "name":"JUNG SANG SOO", "kor_name":"정상수", "img":"https://user-images.githubusercontent.com/86250281/155874075-e9120da7-e123-4234-8574-23661f134149.jpg"}
]
이런 데이터가 내 mock 서버에 저장되어있는 상태이다
let [alphabet, setAlphabet] = useState("");
let alphaBtn = Array.from({ length: 26 }, (v, i) =>
String.fromCharCode(i + 65)
);
버튼을 만들기위한 alpahBtn 변수와 유저가 클릭시 각각의 버튼의 value를 저장할 alpahbet state를 선언했다.
{loading ? (
<div className="spinner">
<Spinner animation="border" variant="primary" />
<p>Loading...</p>
</div> //loading UI용
) : (
alphaBtn.map((item) => {
return (
<button
onClick={(e) => {
setAlphabet(e.target.value);
}}
value={item}
>
{item}
</button>
);
})
)}
alphaBtn 변수에는 A,B,C,D,E.....값이 저장되어 있으므로 map 함수를 통해 하나씩 돌며 렌더링 하게 해주었고, 해당 버튼값을 value에 저장, onClick시 state변경함수로 해당 value값을 가지게 했다
<div className="container">
<div className="main-box">
{mydata.map((x) => { // mydata : 데이터 저장 되어있는 state
if (
x.name.substring(0, 1).toLowerCase() === alphabet.toLowerCase()
) {
return (
<div className="artist">
<img src={x.img} alt={x.name} />
<p>
{x.name} {"(" + x.kor_name + ")"}
</p>
</div>
);
}
})}
</div>
</div>
데이터가 저장되어있는 mydata state에 map함수를 돌렸다
x.name.substring(0, 1).toLowerCase()
-> mydata안에 name에 저장된 값을 substring 함수로 맨 앞글자만 뽑아낸 후 소문자로 변환
alphabet.toLowerCase()
-> 현재 유저가 누른 버튼 value가 alphabet state에 저장되어있다, 소문자로 변환
비교 연산을 통해 같다면 해당 데이터를 렌더링 하게 해주었다
누를때마다 데이터를 검색하기 때문에 데이터가 겁나 많다면 효율성 측면에서는 안 좋을거 같기도 하다, 간단한 토이프로젝트 (단어장 만들기 등) 에 써먹으면 좋을거 같다
import "./App.css";
import "./Main.scss";
import { useEffect, useState } from "react";
import { Spinner } from "react-bootstrap";
import axios from "axios";
function App() {
let [mydata, setData] = useState([]); // 데이터 저장용
let [alphabet, setAlphabet] = useState(""); // 알파벳 클릭시 value 저장용
let [loading, setLoading] = useState(true); // loading UI용
let alphaBtn = Array.from({ length: 26 }, (v, i) =>
String.fromCharCode(i + 65)
);
useEffect(() => {
axios
.get("서버 url")
.then((result) => {
setData(result.data);
setLoading(false);
})
.catch(() => {});
}, []);
return (
<div className="App">
{loading ? (
<div className="spinner">
<Spinner animation="border" variant="primary" />
<p>Loading...</p>
</div>
) : (
alphaBtn.map((item) => {
return (
<button
onClick={(e) => {
setAlphabet(e.target.value);
}}
value={item}
>
{item}
</button>
);
})
)}
{alphabet == "" ? <h1>초기 화면</h1> : null}
<div className="container">
<div className="main-box">
{mydata.map((x) => {
if (
x.name.substring(0, 1).toLowerCase() === alphabet.toLowerCase()
) {
return (
<div className="artist">
<img src={x.img} alt={x.name} />
<p>
{x.name} {"(" + x.kor_name + ")"}
</p>
</div>
);
}
})}
</div>
</div>
</div>
);
}
export default App;