fruitName | color | store | price |
-------------------------------------------------
apple | red | A | 800 |
melon | green | B | 2500 |
orange | | | |
mango | yellow | C | 1200 |
grape | | | |
- 만들고 싶은 기능 -
위처럼 과일 목록 테이블을 만들어야 한다.
단, 과일 이름(fruitName 칼럼)은 항상 나온다.
모든 과일 이름들은 고정으로 출력되고,
나머지 값들은 있을 때만 나온다.
- 문제 -
언뜻 생각하기에 간단할 것 같지만 생각보다 문제가 복잡하다.
일단 서버로부터 과일 정보 목록을 받아와야 한다.
그런데 DB에서는 데이터가 있는 과일만 select 해온다.
데이터가 없으면 그 과일 자체가 select 결과에 없다.
그러면 테이블에서는 그 과일 자체가 출력되지 않는다.
이러면 우리가 만들고 싶은 테이블과 다른 내용이 된다.
우리가 만들고 싶은 테이블은 DB에서 받아온 과일 정보가 있든 없든
과일 이름 자체는 과일 목록에 항상 출력되어야 한다.
- 방법 구상 -
datagrid 테이블에 넣어 줘야 하는 행 데이터 rowData 는 객체들의 리스트다.
보통은 DB에서 select 해온 lsit 를 그대로 rowData 에 넣어준다.
그런데 그렇게 하면 정보가 DB 에 등록되어 있지 않은 과일들은
과일 이름조차 테이블에 출력되지 않는다.
이번에 만들 테이블은 앞에서 말했듯 과일 이름만은 고정으로 출력되어야 하므로
DB에서 불러온 결과가 있든 없든 fruitName 속성은 항상 값이 있어야 한다.
따라서 DB에서 불러온 list 를 그대로 rowData 에 넣어주지 말고,
중간에 map 객체를 하나 만들어 둔다.
mapping 객체 fruitMap 은 DB 에서 불러온 list 를 저장해두는 중간 다리다.
DB에서 불러온 과일 정보를 fruitMap 에 임시로 담아둔다.
const fruitMap = {
apple: {fruitName: "apple", color: "red", store: "A", price: "800"},
melon: {fruitName: "melon", color: "green", store: "B", price: "2500"},
mango: {fruitName: "mango", color: "yellow", store: "C", price: "1200"},
}
테이블에 넣어 줄 rowData 를 생성하는 함수 getRowData() 를 따로 만든다.
getRowData() 함수는 리스트를 반환한다.
그 리스트 안에는 객체들이 담겨 있다.
그 객체 하나하나는 테이블에 출력될 과일의 정보들이 들어 있다.
그중에서 과일 이름 fruitName 속성은 항상 들어 있어야 한다.
그래야 과일 이름들이 테이블에 고정으로 출력되기 때문이다.
반환할 newFruitList 를 만들 때는 요소마다 일단 fruitName 속성을 먼저 넣어준다.
그리고 그 fruitName 속성 이름으로 저장된 과일 정보가 있는지 mapping 객체 fruitMap 안을 뒤져본다.
DB 에서 불러온 결과가 있다면 newFruitList 안에다가 그대로 넣어준다.
없다면 아까 넣어둔 fruitName 속성만 들어 있는 채로 그냥 넘어간다.
이렇게 완성된 newFruitList 를 return 한다.
추가로, 과일 이름들이 들어 있는 리스트를 만들어 두면 편하다.
key 를 이름으로 쓰면 forEach 반복문을 돌릴 수도 있고 비교할 때도 좋다.
_fruitKeyList = ["apple", "melon", "orange", "mango", "grape"];
_fruitKeyList.forEach((ele, idx, arr)=>{
if(fruitMap[ele]) {
// do something
}
});
- 코드 -
@observable
// DB 에서 불러온 list 를 임시로 저장해두었던 mapping 객체 fruitMap
_fruitMap = {};
// 과일 이름들이 들어 있는 리스트
_fruitKeyList = ["apple", "melon", "orange", "mango", "grape"];
@computed
get fruitMap() {
return toJS(this._fruitMap);
}
@action
setFruitMap(data) {
this._fruitMap = data;
}
@computed
get rowData() {
// 테이블에 행 데이터로 들어갈 리스트
let newRowData = [];
// 속성 이름 key 로 쓸 과일 이름들이 들어 있는 리스트를 한 바퀴 돌면서 >
this._fruitKeyList.forEach((ele, idx, arr) => {
// DB 에서 불러온 list 를 임시로 저장해두었던 mapping 객체 fruitMap 을 뒤져보고, 있으면 추가하고 없으면 그냥 둔다.
if(this.fruitMap[ele]) {
newRowData.push(this.fruitMap[ele]);
}
});
}
// DB 에서 불러온 list 를 중간다리 역할 mapping 객체 fruitMap 안에 임시로 넣어둠
setFruitMapEach(fruitListFromDb) {
const newFruitMap = {};
// 속성 이름 key 로 쓸 과일 이름들이 들어 있는 리스트를 한 바퀴 돌면서 >
this._fruitKeyList.forEach((ele, idx, arr)=>{
// DB 에서 불러온 list 안에 해당 key 과일 이름으로 요소가 있는지 확인
const resultFind = this.findByKeyAndVal(fruitListFromDb, "fruitName", ele);
// fruitName 속성은 기본적으로 넣어주고, 거기에 DB 에서 select 해온 과일 정보도 있다면 그대로 복사해서 넣어줌
newFruitMap[ele] = {...resultFind, fruitName: ele};
});
this.setFruitMap(newFruitMap);
}
// 어떤 list 안에 들어 있는 요소들 중에 어떤 key 속성 이름의 값이 특정 값과 일치하는 요소가 있다면
// 그 요소를 반환하고 없다면 빈 객체 반환
findByKeyAndVal(targetList, keyName, val) {
if( !(keyName && targetList && targetList.length > 0 ) ) {
return {};
}
const resultFind = targetList.find((ele, idx, arr)=>{
return ele[keyName];
});
return resultFind || {};
}
- 230214
'React' 카테고리의 다른 글
row 번호 자동으로 뽑아주는 함수 만들기 (0) | 2023.04.04 |
---|---|
[React] 렌더링 기본 개념 정리 - 렌더링/렌더/커밋/가상DOM (0) | 2023.02.06 |
[React] store 에 있는 객체를 view 에 바인딩하여 출력할 때 주의할 점 - setProps (0) | 2023.01.30 |
[React.js] 클래스형 setState 안 될 때 - 덮어쓰기 되는 경우 (0) | 2023.01.23 |
[React] onChange 값이 한 박자씩 늦게 들어갈 때 / observable 변수 렌더링 뒤늦게 반영될 때 (0) | 2023.01.02 |