react) map함수 사용시 클릭시 스타일 바꾸기

이명진·2021년 4월 14일
3

팀 프로젝트시 버튼을 클릭하면 스타일을 변경해줘야하줘야 했다.
하지만 map을 사용해서 li를 돌린 것이라. setState값을 변경하면 스타일이 모조리다 변경되어 버리는 불상사가 생기게 되었다.

멘토님의 도움을 받아서 하나씩 변경이 가능하도록 구현시킬수 있었다.
잊어버리기 전에 벨로그를 작성한다.

방법은 두가지가 있었다.

1. state값 개수만큼 만들기

첫번째 방법은 this.state값을 li개수만큼 만들어서 setState를 활용해 변경해주는 것이였다.

this.state = {
      
      isClicked: Array(TITLES.length).fill(false),
    };

isClicked라는 키를 생성하고 14개의 값을 입력하기에는 지저분해지기 때문에
Array()함수를 사용해서 li길이만큼 만들어 주고 false값으로 채운다.

handleClick = idx => {
    this.setState({
      isClicked: this.state.isClicked.map((element, index) => {
        return index === idx ? !element : element;
      }),
    });
  };

handleClick이라는 함수를 만들어서 클릭시 변경 되도록 하는 함수를 만들어준다.
함수는 this.setState를 실행하여 isclicked값을 변경해주는데
state불변성의 원칙때문에 map을 돌려 새로운 배열을 만들어줍니다.
state불변성의 법칙은 기존의 state값을 직접적으로 변경하지 않고 간접적으로 변경하는 것
우리가 무엇을 클릭해야지 알아야 하기 때문에 함수 인자를 index로 정해줍니다.
idx는 li에서 맵돌릴때의 index; map을 다시 돌리는데 index와 중복되어 헷갈리기 때문에 idx로 사용하였다.
만약 새로 만든 배열의 index값과 클릭해서 접근한 index값이 같을 경우 false값을 true값으로 변경해줍니다. (!element )

{TITLES.map((elm, index) => {
                return (
                  <li
                    className={`buttonList ${
                      isClicked[index] ? 'blue' : 'red'
                    }`}
                    onClick={() => this.handleClick(index)}
                  >
                    <a>
                      <span className="icons">{elm.icon}</span>
                      {elm.content}
                    </a>
                  </li>
                );
              })}

TITLES는 배열로 미리 하드코딩으로 리스트 안의 값들을 만들어 놓았다.
TITLES값을 map을 돌릴 때 li에 하나씩 인자들을 넣어주는데
li를 클릭할 경우 this.handleClick함수가 index값을 받아서 실행이 된다
여기서의 index가 위의 함수에서 idx로 값을 받는것

스타일 값이 안먹어서 blue, red 변수를 만들어 줘서 className에 변경되도록 설정해주었다.
그래서 isClicked가 true이면 파랑 false이면 red로 변경된다.
blue, red 변수에 css값을 미리 주었다.
이렇게 해서 리스트에 인덱스를 받아서 클릭시 인덱스의 스타일을 변경하게 한다.

2. 컴포넌트를 만들어서 map돌리기

사실 이 방법이 이해하기에 더쉬웠다.
test컴포넌트를 제작해주고 맵을 돌릴때 test컴포넌트를 각각 돌린다.

{TITLES.map(elm => {
                return <Test icon={elm.icon} content={elm.content} key={elm} />;
              })}

test 컴포넌트

class Test extends Component {
  state = { isClicked: false };

  onClick = () => {
    this.setState({ isClicked: !this.state.isClicked });
  };

  render() {
    const { isClicked } = this.state;
    const { icon, content } = this.props;
    return (
      <li
        className={`buttonList ${isClicked ? 'blue' : 'red'}`}
        onClick={this.onClick}
        // style={{ backgroudColor: isClicked ? 'blue' : 'red' }}
        // style={{ backgroudColor: 'red' }}
      >
        <a>
          <span className="icons">{icon}</span>
          {content}
        </a>
      </li>
    );
  }
}

state를 만들어 주면 컴포넌트를 map돌리게 될때 각각 state 가 있기 때문에
개별로 스타일이 가능하게 된다.

profile
프론트엔드 개발자 초보에서 고수까지!

2개의 댓글

comment-user-thumbnail
2022년 9월 21일

감사합니다 많은 도움이 되었습니다

답글 달기
comment-user-thumbnail
2022년 10월 5일

와 이거때문에 너무 고생하고 있었는데 됐어요.
너무 감사합니다!!

답글 달기