이번에 진행하는 프로젝트에 처음으로 리액트를 사용하게 되었다.
그리드는 뭘로 사용할까 하다가 gridjs를 정하고 테스트해보는데 디자인도 깔끔하고 사용성도 편리한 거 같았다.
그리고 클릭이벤트를 찾아보는데 뭔가 쉽게 검색이 되지 않았고
행 변경시에 색상 변경은 기존에 css와 부치는지는 한참을 고생해서 적용했다.
기본으로 제공하는 부분이 동작을 안 해서 어쩔 수가 없었는데 임시방편으로 강제 변경을 진행해 주었다.
혹시 같은 고민을 하고 있다면 다른 부분은 참고를 위해서 넣은 부분이고 클릭이벤트와 그안에 색상 지정하는 부분만 필요하다면 참고하면 될 거 같다.
import { Grid, h } from 'gridjs';
import "gridjs/dist/theme/mermaid.css";
import React, { useEffect, useState, useRef } from 'react';
import '../../styles/Box.css';
const Stock1 = () => {
const [data, setData] = useState(null);
const [selectedCode, setSelectedCode] = useState('005930');
const [selectedName, setSelectedName] = useState('삼성전자');
const gridRef = useRef(null); // grid element에 접근하기 위한 ref
useEffect(() => {
const fetchData = async () => {
try {
const response = await axiosInstance.get('/todaydata');
const tableData = JSON.parse(response.data.data.list).map(item =>
[item.RANK, item.NAME, item.CLOSE, item.CHA_PER, item.CHA_DIV, item.CODE]);
setData(tableData);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []);
useEffect(() => {
if (data && gridRef.current) {
const grid = new Grid({
columns: [
{ id: 'RANK', name: 'RANK', width: '10%' },
{ id: 'NAME', name: 'NAME', width: '40%' },
{ id: 'CLOSE', name: 'CLOSE', width: '20%' },
{
id: 'CHA_PER',
name: 'CHA_PER',
width: '15%',
formatter: (cell, row) => {
const chaDiv = row.cells[4].data;
const color = chaDiv === 1 ? 'red' : 'blue';
return h('span', { style: { color: color } }, cell);
},
},
{ id: 'CHA_DIV', name: 'CHA_DIV', width: '0%', hidden: true },
{ id: 'CODE', name: 'CDODE', width: '0%', hidden: true }
],
data: data,
search: true,
pagination: {
limit: 2500,
summary: true
},
style: {
table: {
width: '100%',
},
row: {
// 선택된 행의 스타일
selected: {
backgroundColor: 'lightblue',
}
}
}
});
// 이벤트 등록 (rowClick)
grid.on('rowClick', (event,row) => {
const rowData = row.cells.map(cell => cell.data); // 각 열의 데이터를 배열로 추출
const rowElement = event.target.closest('tr');
const rowIndex = Array.from(rowElement.parentNode.children).indexOf(rowElement);
// 모든 행에서 'selected' 클래스 제거
const rows = rowElement.parentNode.children;
Array.from(rows).forEach((row) => {
row.classList.remove('selected');
// 이전 스타일 초기화
Array.from(row.cells).forEach(cell => {
cell.style.backgroundColor = ''; // 모든 셀의 배경색 초기화
});
});
// 현재 선택된 행의 배경색을 변경
rowElement.classList.add('selected');
// 선택된 행의 모든 셀에 배경색 적용
Array.from(rowElement.cells).forEach(cell => {
cell.style.backgroundColor = '#e6f7ff'; // 선택된 셀 배경색 변경
});
});
grid.render(gridRef.current); // grid 렌더링
}
}, [data]);
if (!data) {
return (
<div>
<NavDetail value='stock' />
<div>Loading...</div>
</div>
);
}
return (
<div>
<div style={{ display: 'flex', height: 'calc(100vh - 60px)' }}>
<div ref={gridRef}></div> {/* Grid가 렌더링될 요소 */}
</div>
</div>
);
};
export default Stock1;