팀 프로젝트 - 원에 이름 넣기

BooKi·2022년 4월 20일
0
post-thumbnail

팀 프로젝트 - 원에 이름 넣기

지난번

지난번에 1번 원에서 고른 선수가 2번에서 뜨는걸로 문제가 생겼었고 거기서 멈췄다

이유를 알아냈다

나는 <MENU>태그와 <Draggable>태그가 한 쌍인줄 알았다

그래서 2번째 원을 만들때도 메뉴,드래거블을 그대로 하나 더 복사했다

근데 메뉴는 드래거블마다 한개씩 필요한게아니라 그냥 하나만 존재해도 되는것이었다

즉 첫번째 메뉴 온클릭 이벤트에 걸어두었던 name1 이벤트 핸들러는 불리지가 않고

두번째 메뉴 태그안에 있는 온클릭 이벤트만 불렸던 것이다

여기서 또 문제가 찾아왔다

원래 각 원에 맞는 이벤트 핸들러를 만들었고 그대로 걸어주었다

근데 메뉴태그가 하나만 있어야 했기에 그렇게는 구현할 수 없었다

그렇게 된다면 지금 우리가 선택한 선수가 어느 원에서 불렸는지 어떻게 알 수 있지??

구현

메뉴 태그에있는 이벤트로는 알 수 없을것이라고 생각했다

그래서 원에 있는 이벤트가 뭔가 찾아보던중 하나를 발견했다

드래거블 안에 있는 요소중 버튼태그가 하나 있다

그 버튼태그는 클릭하게되면 메뉴를 불러오는 온클릭이벤트가 걸려있다

여기서 발견을 했다

그 이벤트에서 currentTarget을 이용해서 버튼의 id값을 받아온다

그리고 그 id를 butNum이라는 state에 저장을 하였다

이후 onNamehandler를 switch를 사용하여 butNum를 가지고 분기를 해줬다

  const onNameHandler = ({_id, id, name, already, Change}) => {
    switch(buttonNum){
      case "button1" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 3 ? { ...position, name: name} : position)
        )
        return SetName1(name)
      case "button2" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 3 ? { ...position, name: name} : position)
        )
        return SetName2(name)
      case "button3" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 3 ? { ...position, name: name} : position)
        )
        return SetName3(name)
      case "button4" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 4 ? { ...position, name: name} : position)
        )
        return SetName4(name)
      case "button5" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 5 ? { ...position, name: name} : position)
        )
        return SetName5(name)
      case "button6" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 6 ? { ...position, name: name} : position)
        )
        return SetName6(name)
      case "button7" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 7 ? { ...position, name: name} : position)
        )
        return SetName7(name)
      case "button8" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 8 ? { ...position, name: name} : position)
        )
        return SetName8(name)
      case "button9" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 9 ? { ...position, name: name} : position)
        )
        return SetName9(name)
      case "button10" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 10 ? { ...position, name: name} : position)
        )
        return SetName10(name)  
      case "button11" :
        SetPositionList(PositionList.map((position) =>
        position.circle === 11 ? { ...position, name: name} : position)
        )
        return SetName11(name)  
      default:
        return null
    }
  }

이렇게 핸들러를 만들고 이 핸들러를 메뉴에 그대로 걸어두었다

버튼을 클릭하면 먼저 버튼의 id값이 state에 저장되게 되고

선수를 클릭하면 그때 네임핸들러가 작동하게되기때문에 우리가 원하는대로 구현이 되었다

이제 우리가 해야하는것은 선수 교체가 일어났을 때

원래있던 선수의 already값을 다시 false로 바꾸어주는것이다

지금 메뉴에 걸려있는 클릭핸들러는 2개이다

  1. 클릭하면 열린 팝업 창을 닫아야 하기때문에 창을 닫는 함수
  2. 클릭했을 때 선수의 이름을 원에 띄우는 함수

선택된 선수의 already값을 true로 바꾸는 것은 1번에 작성을 하였다

처음에는 true로 바꾸기 전에 모든 선수의 값을 false로 바꾸면 되지않을까? 생각했는데

생각해보니 그건 원이 하나일때나 가능한 얘기이고, 실제로 구현을 했을때도 하나도 작동하지 않았다

그래서 한참을 고민했다

그걸 구현하려면 이미 그 원에 담겨있던 선수의 정보를 알고있어야하는데

온클릭 이벤트이다보니 이전값을 저장을 할 수가 없었다

한참을 골똘히 생각해보았다

그러다가 번뜩하고 좋은 생각이 났다

바로 Name State를 사용하는것이다

클릭이벤트가 끝나면 name에는 현재 원에 등록된 선수의 이름이 담겨있다

그래서 네임핸들러에서 이름을 변경하기 전에 name 스테이트에 null이 아니라면

name스테이트에 담긴 값과 db에서 받아온 리스트를 비교해서 같은 사람의 already를 다시 false로 바꾸어주는것이다

        if(Name1 === null){ 
          return SetName1(name)
        } else {
          setPlayerList(playerList.map((player) =>
          player.name === Name1 ? {...player, already: false}: player))
          return SetName1(name)

모든것은 완벽했다

근데 작동을 하지않았다

심지어 선택된 선수를 true로 바꾸어주는것도 처음에만 가능하고 두번째 선수부터는 작동하지않았다

그래서 확인을 하기위해 already를 변경하는것이 아닌 id를 100으로 변경해보기로 했다

2번의 콘솔을 찍었다

처음찍은건 id를 변경하는 함수 안에서 찍었고 두번째는 함수 밖에서 찍었다

확인한 결과 함수자체에는 문제가 없고 제대로 100이 들어가는것을 알 수 있다

근데 함수가 끝나야만 그 값이 변경되는것도 알수있었다

여기서 뭔가 스쳐지나갔다

지금 나는 온클릭이벤트에 두가지가 변경되게 되어있다

  1. 선택된선수를 true로 바꾸기
  2. 기존의 선수를 false로 바꾸기(지금은 id를 100으로 바꾸는거로 테스트중)

3번을 일부러 2번을 골라봤다

2번을 골라야 처음에 name에 3번의 값이 들어가고 두번째 불릴 때 id가 100으로 바뀌는 로직이니까

사진을 보면 알겠지만 두번째 함수는 제대로 작동을 하는데 1번 함수는 작동을 안한다

생각을 해보니 한 이벤트가 끝나기전에 2번의 변경이 있기때문에 마지막 변경만 적용이된다는 결론을 내렸다

그래서 두가지의 방법이 생각이 났다

  1. 2번의 함수를 클릭이벤트 밖으로 빼기
    -> 클릭이벤트에서 들어오는 props를 기준으로 값을 변경하기때문에 이방법은 불가능하다고 생각했다
  2. 두번의 set을 하는게 아니라 한번에 두가지의 값을 변경하기
    -> 변경하는 정보가 다르고 변경하는 선수가 다르다.
    이부분이 구현이 가능한지 알아보자

그래서 일단 2번 방법으로 해보기로하였고 찾아보았다

map으로 변경을하는데 map안에 두가지의 기능?을 넣을 수 있나? 를 먼저 알아보았다

아무리 찾아도 map안에 두가지 기능을 넣는 방법은 없어보였다

그래서 setstate를 두번 변경할 순 없나? 싶어서 검색해봤다

그랬더니 이 블로그의 제목이 뭔가 느낌이 왔다

비동기라는 말에 어?? 싶은 생각이 들었고 들어가서 읽어보니까 내가 생각한게 맞았다

제일 마지막 set만 적용이 되는것이다

그래서 거기 나온것거처럼 함수형으로 변경하였다

setPlayerList((prev) => prev.map((player) => player.id === id ? { ...player, already: !already} : player))
if(Name1 === null){ 
          return SetName1(name)
        } else {
            setPlayerList((prev) => prev.map((player) => player.name === Name1 ? { ...player, already: false} : player))
          return SetName1(name)
        }

기대되는 순간이다 제대로 작동을 할까??

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 제대로 작동을 한다

ㅠㅜㅠㅠㅠㅠㅠㅠㅠ 이게 제일 어려웠는데 이렇게 해결이 되니까 너무 뿌듯하다!!

이제 팀 포메이션쪽은 구현이 거의 끝이났다!!!!

profile
성장을 보여주는 기록

0개의 댓글