Hold Shift to Check Multiple Checkboxes

Woohyun Jang
6 min readOct 18, 2018

--

이번에는 클릭 이벤트를 받을 때 Shift키가 눌려져 있는 상태라면 여러 체크 박스들을한 번에 클릭하도록 구현해볼 것이다. 초기 코드는 여기에 있다.

App component안에 Inbox component를 포함하고 있는 InboxContainer를 넣어주었고, Inbox에서 각각의 요소들을 Item component로 분리했다.

//components/Item.jsimport React from 'react';

const Item = ({text, checked, onClick}) => {
return (
<div className="item">
<input type="checkbox" checked={checked} onChange={onClick}/>
<p>{text}</p>
</div>
);
};

export default Item;

각각의 요소를 나타내는 Item은 큰 로직 없이 text와 checked정보만을 가지고 View의 모양만 잡아주기 때문에 React component class로 따로 만들지 않고 파라미터를 받는 함수로 만들었다.

// components/Inbox.jsimport React, { Component } from 'react';
import './Inbox.css';
import Item from './Item';

class Inbox extends Component {
render() {
const { items, click } = { ...this.props };
const itemList = items.map( (item, index) => {
return (
<Item
key={index}
text={item.text}
checked={item.checked}
onClick={e => click(e, index)}
/>
)
});

return (
<div className="inbox">
{itemList}
</div>
)
}
}

export default Inbox;

Inbox component는 InboxContainer로부터 상태와 dispatch function을 전달받아 items의 수만큼 Item을 만들어준다.

// containers/InboxContainer.js
import { connect } from 'react-redux';

import Inbox from '../components/Inbox';
import { click } from "../actions";

const mapStateToProps = state => {
return state;
};

const mapDispatchToProps = dispatch => {
return {
click: (e, index) => {
dispatch(click(e, index));
}
}
};

const InboxContainer = connect(mapStateToProps, mapDispatchToProps)(Inbox);

export default InboxContainer;

InboxContainer는 현재 store에 있는 state를 그대로 Inbox component로 넘겨주고 클릭시 dispathch() 시켜주는 함수를 만들어준다. 한 가지 특이한 점은 기존과 달르 click() function의 파라미터로 index뿐 아니라 event(e)를 함께 넘겨준다는 점인데, event 발생 시점에 shift키가 눌려있는지를 reducer에서 확인하기 위해 넘겨준다.

// actions/index.js
export const CLICK = 'CLICK';

export function click(e, index) {
return {
type: CLICK,
index: index,
shiftKey: e.nativeEvent.shiftKey
}
}

이번 프로젝트에서 필요한 action은 단 하나. click action이다. 첫 번째 인자로 넘어온 event는 우리가 흔히 알고 있는 addEventListener()로 등록할 때 넘어오는 event를 react에서 cross-browser wrapper로 감싸준 객체로써, 원래 우리가 알고 있는 event 객체를 사용하기 위해서는 event.nativeEvent로 접근해야 한다.

reducers/index.js

reducer에서 초기 mock data를 만들어주었고, CLICK action이 들어왔을 때의 로직 처리를 해주었다.

shiftKey가 눌려져있지 않거나 이전에 눌려있던 체크박스가 없다면 기본적으로 아이템을 하나씩 토글하는 로직이 작동한다. 다른 items는 그대로 반환하고, 해당 index의 item은 checked를 토글하여 새 state를 만들어 반환해주었다.

shiftKey를 누르고 그룹선택을 할 때는 먼저 범위를 정해야 한다. 현재 shift key를 누르고 누른 아이템과 이전에 클릭한 아이템 사이에 해당하는 아이템은 checked로 바꾸어주고, 나머지는 다시 그대로 반환해주었다.

실행화면은 다음과 같다. shift키를 누르고 그룹 선택이나 누르기 않고 개별 토글이 가능하다.

Github Source Code

--

--

No responses yet