Front-End/React
[리액트/React] 리액트에서 className 동적으로 사용하여 클릭한 div에만 CSS 적용하기
코코월드주인장
2023. 11. 6. 16:48
의외로 자주 사용되는 스킬이라 이번에 두번째 만들게 되면서 포스팅하게 되었다.
여러가지 배열값들을 나열하여 일치된 classname 중에서 특정 div값을 클릭하였을 때, 해당 요소만 CSS를 변경하여 사용자에게 보여주는데 이는 classname 동적으로 활용하는 방법이다.
보통 useState를 사용하여 값을 상태관리하겠지만 본 사용자는 리덕스를 사용하고 있어 slice를 통해 상태관리하였다.
따라서, Redux와 useState 두 가지 사용방법을 적용해보겠다.
1. Redux Toolkit의 Slice를 사용해 적용하기
메인 컴포넌트의 HTML
<div className="listview-container">
{storeObj.state.employeeList?.map((item, idx) => (
<div
className={`listview-content-box${
storeObj.state.selectedIndex === idx ? "-selected" : ""
}`}
onClick={() => storeObj.callbacks.selecteNameState(idx)}
>
<div className="listview-name-font">{item.name}</div>
<div className="listview-count-font">{item.ASM}건</div>
</div>
))}
</div>
코드 설명
- onClick 이벤트를 실행시키면 해당 item의 idx를 파라미터로써 전달한다.
- 메인 컴포넌트의 callbacks에 선언한 selecteNameState를 통해 slice에 parameter가 전달된다
- Redux slice에서 상태가 저장되고 메인 컴포넌트의 state를 통해 저장된 상태값을 호출한다
- 상태값의 변화가 일어날때마다 employeeList의 map은 item을 나열하고, 나열하는 item의 idx와 idx가 저장된 storeObj.state.selectedIndex를 비교하여 일치하다면, 그 요소는 내가 클릭한 요소임이 증명된다.
- 그 요소는 삼항연산자를 통해 className이 다른 요소들과 공통된 listview-content-box가 아닌 listview-content-box-selected로 선언되고 해당하는 listview-content-box-selected의 의도된 CSS가 적용되게 된다.
메인 컴포넌트의 SAGA state, callbacks
const storeObj = {
state: {
isSelectedState: useSelector((state) => state[pageID].isSelectedState),
employeeList: useSelector((state) => state[pageID].employeeList),
selectedIndex: useSelector((state) => state[pageID].selectedIndex),
},
callbacks: {
selecteNameState: useCallback((idx) => {
dispatch(actions.selecteNameState(idx));
}, []),
getEmployeeList: useCallback(() => {
dispatch(actions.getEmployeeList());
}, []),
},
};
Redux Slice
const initialState = {
isSelectedState: false,
seletedIndex: 0,
};
const reducers = {
selecteNameState: (state, action) => {
state.isSelectedState = !state.isSelectedState;
state.selectedIndex = action.payload;
},
};
useState 버전도 따로 추가해서 업데이트 해야하는데,
코드 만지다 온거라 마저 마무리하고 와서 적용해볼게용 (총총,,)
오랜만에 티스토리 블로그 방문했네. 신나는 리액트시간~
