체크박스 useState구현 안되는 문제 질문드립니다.

안녕하세요. 리액트 작업을 하다가 도저히 해결이 안되어 질문올립니다!
전체해제라는 체크박스에 체크를 하면 li에 있는 체크박스들이 전부 해제되게끔 구현하고 싶은데
setList(copyList)를 주었는데도 리렌더링이 안돼서 화면상에 바뀌는 부분이 없습니다.

우선 list가 기본값이긴 한데 데이터 불러오면 list 데이터가 유저가 기존에 저장했던 값으로 바뀌기 때문에 따라서 a1이 true일 수도 있고 전부true거나 전부false거나 할 수도 있는 상황이라 그냥 버튼누르면 전부 check상태가 false로 바꾸고 싶었습니다.

구글링을 해보니까 같은 값을 넣어줘서 리액트가 리렌더링을 안시키는거라고 해서
setList([…copyList])도 해보고 여러방법을 시도해봤는데 바뀌는게 없는거같습니다 ㅠㅠ
list === copyList는 분명히 false가 나오는데 말이에요

copyList 배열의 마지막 객체를 삭제하면 또 갱신이 되는데
저는 다른 a1,b1,c1 객체 전부 넣고 딱 check를 전부 false로 바뀌어서 업데이트 되게 하고싶습니다

어느부분이 잘못된걸까요 ?

function App() {
  const [list, setList] = useState([
    {
      id: 'a1',
      check: false,
    },
    {
      id: 'b1',
      check: false,
    },
    {
      id: 'c1',
      check: false,
    },
  ]);

  const changeAll = (e) => {
    if(e.target.checked){
      const copyList = list.slice();
      for (let i = 0; i < copyList.length; i++) {
        copyList[i].check = false;
      }
      setList(copyList); // 이부분이 해결이 안되는 거 같습니다.
    }
  };

useEffect(() => {
   setList(..) // 여기에 서버에서 불러온 데이터로 바뀝니다. c1이 true일 수도 있고 유저가 저장한 상태로 setList됩니다.
}, [])

  return (
    <div className="wrap">
      <input type="checkbox" onClick={changeAll} />
      <ul>
        {list.map((n) => {
          return (
            <li>
              {n.id}
              <input type="checkbox" checked={n.check} />
            </li>
          );
        })}
      </ul>
    </div>
  );
}

저기 setList(copyList); 위에서 copyList 콘솔 찍어보시구 값이 제대로 오나 확인 해보셨나요?

네 제가 원하는대로 check: false로 전부 바뀌어서 찍히긴 하는데 화면단에서 변경은 없어요ㅠ

var copyList = list;
for (let i = 0; i < list.length; i++) {
  copyList[i]['check'] = !copyList[i]['check'];
}
setList([...copyList]);

해보실래요?
안되시면

var copyList = list;
for (let i = 0; i < list.length; i++) {
  copyList[i]['check'] = !copyList[i]['check'];
  setList([...copyList]);
}

이렇게도 해보세요!

두방식 모두 해제체크하면 전부 선택(check: true)로 바뀌는거 같아요;;
그 상태로 저장을 눌러봤는데 저장이 안되는거 보니 다른 부분도 잘못짰나 싶은 생각도 들구요

useEffect에 dependency를 추가하지 않아서 안되는거 아닐까요?
useEffect(() => {
setList(…)
}, [list])

거기에 추가하면 무한루프 돌더라구요…

왜냐하면 list는 레퍼런스 타입이라서 setList(copyList)를 하면 useEffect의 dependency는 새로운 어레이를 만들고 있다고 생각할거에요. 그래서 useEffect는 어? 새로운 어레이 받으니까 상태가 변하네? 어? 그러면 리렌더링해야겠네? 무한반복이죠. 그래서 어레이 안에 있는 오브젝트의 value로 dependency를 써야 deep equity check가 되어서 무한루프에 안빠지게 될거에요.

useEffect(() => {
 setList(…)
}, '[list에 있는 오브젝트의 id']) // dependency에 들어갈 코드를 말로 풀었어요 ^^;;

혹은

useEffect(() => {
  setList(…)
}, [JSON.stringify(list)]) // 이거는 비효율적이라네요 https://stackoverflow.com/questions/59467758/passing-array-to-useeffect-dependency-list

맨 처음 댓글에 단 솔루션은 죄송해여

당연히 false상태에서 event가 일어나면 true로 바뀌는 식입니다
true일때는 false로 바뀌구요

제가 리액트를 잘 몰라서 이해가 안되는데 그럼
useEffect(() => {
setList(…)
}, [list[0].id]) 이렇게 하란 말씀이신가요…list에 객체가 여러개 들어가있는데 어떤거의 id를 하라는 말씀이신지 잘 모르겠어요

저는 기존값이 true false 상관없이 무조건 모든 li 체크박스가 false가 되어야하는데 그럼 알려주신 방식으로는 불가능한건가요…?
그리고 체크되어있는(true)건 false로 안바뀌던데ㅠ

네 그렇게 하면 되는데 list[0].id를 하면 list[0]에 있는 것만 체크되는 거니까 그 이외의 오브젝트들의 id도 deep equity check를 하도록 해야겠죠? 근데 지금 코드를 어떻게 짜야할지 생각이 안나서 말로 풀었어요 ^^;; 죄송요
그리고 이 article이 도움이 될 거 같아요 https://dmitripavlutin.com/react-useeffect-infinite-loop/

[]에 해당되는거 다 넣어봤는데도 해결이 안되네요… 제가 코드를 전체적으로 잘못짰나봅니다ㅠㅠ 공유해주신 글은 읽어볼게요! 감사합니다!

너무 늦게 확인했네요ㅠㅠ 혹시 해결하셨나요?

앗…넵 방금 원인을 알아냈는데… 제가 checkbox 컴포넌트 작성에서 true, false를 받아오는 부분 잘못 작성했던게 문제였던거 같습니다… 도움주신 분들 모두 감사합니다 ㅠㅠ