(수정2 - 1/20) 체크박스 수정, 전체 체크박스 선택

개발공부·2022년 12월 20일
0
post-thumbnail

* 1/20 수정

▶ 전체 체크박스 선택 시 오류 발생
전체 데이터 변경 시 개별 항목들(wordLists) 내의 유저 Id와 mysql에서 받아온 data의 UserId가 같아야 하는데, 이를 id로 입력함

const changeStatus = state.wordLists.find(
(v) => v.UserId === data[0].UserId
);

status가 "C"일 때는 checkedWordList 내에 데이터가 채워지나, "A"일 때는 checkedWordList는 아무것도 없어야 함

if (showStatus) {
state.checkedWordList.length = 0;
}

* 결과

1) 개별 체크박스 클릭 시 체크된 단어 개수 변동

2) 전체 체크박스 클릭 시 단어 개수 변동 및 체크박스 checked 변화하기

* 코드 작성하면서 생긴 문제

status가 변할 때마다 (C <-> A) redux에 적용하는 것이 문제

const data = action.payload; //{id: 1, status: "A"}
const changeStatus = state.wordLists.find((v) => v.id === data.id);

  if (changeStatus) {
    changeStatus.status = data.status;
  }

* 코드

[components/WordItem.js]

const onChangeSelected = useCallback((e) => {
    const checkboxClicked = e.target;
    const wordIndex = e.target.value;

    if (checkboxClicked.checked) {
      setBChecked(true);
      dispatch(changeStatusWordRequest({ id: wordIndex, status: "C" }));
    } else if (!checkboxClicked.checked) {
      setBChecked(false);
      dispatch(changeStatusWordRequest({ id: wordIndex, status: "A" }));
    }
  }, []);
  
  <input
              checked={bChecked}
              onChange={onChangeSelected}
              value={word.id}
              name="checkItem"
              type="checkbox"
              className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
            />

[wordSaga.js]

function changeStatusAPI(data) {
  return axios.patch(`/word/${data.id}/${data.status}`, {
    id: data.id,
    status: data.status,
  });
}

function* changeStatus(action) {
  try {
    const data = action.payload;
    console.log("data", data);
    const result = yield call(changeStatusAPI, data);
    yield put(changeStatusWordSuccess(result.data));
  } catch (error) {
    yield put(changeStatusWordError(error));
    console.log(error);
  }
}

[routes/word.js]

router.patch("/:id/:status", isLoggedIn, async (req, res, next) => {
  // PATCH /word/10/status
  try {
    await Word.update(
      {
        status: req.params.status,
      },
      {
        where: {
          id: req.params.id,
          UserId: req.user.id, //작성자가 본인이 맞는지?
        },
      }
    );

    res
      .status(201)
      .json({ id: parseInt(req.params.id), status: req.params.status });
  } catch (error) {
    console.error(error);
    next(error);
  }
});

[wordSlice.js]

 changeStatusWordSuccess: (state, action) => {
      const data = action.payload;
      state.changeStatusWordLoading = false;
      state.changeStatusWordComplete = true;

      const changeStatus = state.wordLists.find((v) => v.id === data.id);

      if (changeStatus) {
        changeStatus.status = data.status;
      }
    },

[전체 체크박스 체크를 만들면서 생긴 오류들]

▶ 왜 수정했나?

  • 기존 backend 부분인 axios에서 파라미터 주소와 관련해서 수정

▶ 핵심은 사용자의 아이디 값(id)를 전달하면 status 전체가 다 바뀌는 것

(status가 모두 A -> C로 변하거나 C -> A로 변함)

{id: 1, english: 'hi', korean: '안녕', type: 'easy', status: "A"}, 
{id: 2, english: 'hello', korean: '안녕', type: 'easy', status: "A"}, 
{id: 3, english: 'test', korean: '테스트', type: 'easy', status: "A"}  

내용을 checkboxAll이란 체크박스 선택 시

{id: 1, english: 'hi', korean: '안녕', type: 'easy', status: "C"}, 
{id: 2, english: 'hello', korean: '안녕', type: 'easy', status: "C"}, 
{id: 3, english: 'test', korean: '테스트', type: 'easy', status: "C"} 변경
  • 방법 1(사용 안 함)
  • 방법2(결론)
  • 모든 id값을 일일히 체크하는 것은 불가능
  • sequelize Op 이용

[Op.gt]: 0 // id 조건을 > 0 하게 만듦

  • 원하는 콘솔 결과
  • 어떤 id값이든(여기서는 데이터의 id가 아닌 유저의 id로 값을 넣음) > 0보다 크거나 (or을 넣은 건 id가 둘 중 하나의 조건에는 무조건 성립하도록 하기 위함

(콘솔 결과) Executing (default): UPDATE words SET status=?,updatedAt=? WHERE (id > 0 OR id = ?) AND UserId = ?

(mysql) update next_engword.words set status = ? where id= ? or id > 0 and UserId = ?;

* 오류

* 해결책

  • nodemon 다시 설치(nodemon: 서버 코드 변경 시 서버 새로고침)

npm uninstall nodemon
npm install nodemon

  • 컴퓨터 아예 재부팅

코드 수정 시 콘솔에 이런 식으로 나와야 함
[nodemon] restarting due to changes...
[nodemon] restarting due to changes...
[nodemon] starting node server.js

* 코드

[component/WordList.js]

 const showStatus = wordLists.filter(
    (word) => word.status === "C" && word.UserId === UserId
  ).length;

  const allWord = wordLists.filter((word) => word.UserId === UserId).length;


//useEffect에서 조건(filter) 수행 시 useEffect에 들어가는 두 번째 값(배열)을 정확히 지정하기 어려움
//두 번째 값에 wordLists 같은 걸 넣으면 무한 반복

const onChangeAllSelected = useCallback((e) => {
    const checkboxClicked = e.target;
    const userId = e.target.value;

    if (checkboxClicked.checked) {
      setBChecked(true);
      dispatch(changeStatusWordAllRequest({ status: "C", userId: userId }));
    } else if (!checkboxClicked.checked) {
      setBChecked(false);
      dispatch(changeStatusWordAllRequest({ status: "A", userId: userId }));
    }
  }, []);
  
  return (
   <input
           checked={showStatus > 0 ? true : false}  // checked={bChecked}로 넣으면 아무것도 체크 안 되어 있어도 체크되어 있다고 나옴
            onChange={onChangeAllSelected}
            value={UserId}
            name="checkItem"
            type="checkbox"
            className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
          />
          전체 선택 / 해제
        </div>
        <p>
          체크된 단어 개수 :{showStatus}/{allWord}
        </p>
  )

[wordSaga.js]

function changeStatusAllAPI(data) {
  return axios.patch(`/word/all/${data.userId}/${data.status}`, {
    status: data.status,
    userId: data.userId,
  });
}

function* changeStatusAll(action) {
  try {
    const data = action.payload;
    const result = yield call(changeStatusAllAPI, data);
    yield put(changeStatusWordAllSuccess(result.data));
  } catch (error) {
    yield put(changeStatusWordAllError(error));
    console.log(error);
  }
}

[routes/word.js]

router.patch("/all/:userId/:status", isLoggedIn, async (req, res, next) => {
  // (전체 수정) PATCH /word/status/1(userId)
  try {
    await Word.update(
      {
        status: req.params.status,
      },
      {
        where: {
          [Op.or]: [{ id: { [Op.gt]: 0 } }, { id: req.params.userId }],
          UserId: req.user.id,
        },
      }
    );
     const fullWord = await Word.findAll({
      where: { status: req.params.status },
    });
    console.log("fullWord", fullWord);
    res.status(200).json(fullWord); //game쪽에 정보 전달하기 위함
    res
      .status(200)
      .json(fullWord);
  } catch (error) {
    console.error(error);
    next(error);
  }
});

[wordSlice.js]

 const data = action.payload;
      state.changeStatusWordLoading = false;
      state.changeStatusWordComplete = true;

      const changeStatus = state.wordLists.find(
        (v) => v.UserId === data[0].UserId
      );
      const showStatus = state.wordLists.find(
        (v) => v.UserId === data[0].UserId && v.status === "C"
      );

      if (changeStatus) {
        state.wordLists.map((word) => {
          word.status = data[0].status;
          state.checkedWordList.length = 0;
          state.checkedWordList = state.checkedWordList.concat(data);
        });
      }
      if (showStatus) {
        state.checkedWordList.length = 0;
      }

* array.find, filter, map 비교

▶ find
주어진 판별 함수를 만족하는 첫 번째 요소의 값을 반환합니다. 그런 요소가 없다면 undefined를 반환

▶ filter
주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환

▶ map
배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환

profile
개발 블로그, 티스토리(https://ba-gotocode131.tistory.com/)로 갈아탐

0개의 댓글