careerViewTable.js
//전체 체크가 되었는지 아닌지 확인하기 위한 state변수
const [isSelectAll, setIsSelectAll] = useState(false);
//전체선택 (표의 헤더부분에 있는 체크박스 클릭시 실행)
const onSelectedAll = (e) => {
console.log(e.target.checked); //클릭하면 true가 나옴
setIsSelectAll(e.target.checked);
//👉 한번check를 클릭하면 event가 발생하게되어 true, 한번또클릭하면 false
//👉그 값을 setIsSelectAll변수에 넣어줌.그리고 난후 랜더링됨.
//그래서 checked됬다가 안됬다가. 하는것을 보여줌
}
return (
<tbody>
{careerList.map((e) => <tr key={e.id}>
<td><input
type="checkbox"
checked={isSelectAll}
/></td>
<td>{
e.company
}</td>
<td>{e.position}</td>
<td>
{e.start_date} - {e.end_date}
</td>
<td onClick={() => onDeleteCareer(e.id)} style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
cursor: 'pointer'
}}><DeleteSweepIcon /></td>
</tr>)}
</tbody>
)
export default CareerViewTable;
체크된 녀석을 찾아서 delete해줘.
6개의 행중에서 true인 애들만 삭제해줘. 여기서, 6개모두 기억해줘야함, 그래야 3개가 checked되었는지 몇개가 checked 가 되었는지 알수있다.
알아보기전에, 그전에 잠깐 ❗️
일반변수
👉 값이 변경되어도 re-rendering 되지 않는다.
re-rendering 될때 "초기값"이 나온다.state 변수
👉 값이 변경되면 re-rendering 된다.
re-rendering 되더라도 자기자신의 "값을 기억한다".ref 객체
👉 값이 변경되어도 re-rendering "되지 않는다".
re-rendering 될떄 자기자신의 "값을 기억한다".
똑같은 화면을 다시 그릴필요는 없잖아❓
그래서, state변수
는 바뀔때 마다 리렌더링이 되니까🤨 안좋음
.. 낭비잖아❗️❗️ 전체 리렌더링안하고.. 바뀐부분만 하고싶은데 ..
객체안에는 key값이 하나 있는데,
current
가있다. 이것말고는 아무것도 🚫
const MyComponent = () => {
let a = 10; //일반변수
//re-rendering 되어도 자기자식 값을 기억. 자기자신이 변하면 re-rendering 시키는것
let [b, setB] = useState(10); //state변수
// re-rendering될때 자기 자신의 값을 기억. 자기 자신의 값이 수정되어도 re-rendering 안시키고싶음
let [c, setC] = useState(10); //state변수
//re-rendering될떄 자기 자신의 값을 기억.
//자기 자신의 값이 수정되어도 re-rendering 안시키고싶음
let c = useRef(10); //ref객체
let c = useRef({name:'홍길동', age:10}); //ref객체
let c = useRef(null);
//input도 객체니까 .. input에 ref객체를 연결하면 input의 값을 얻어올수있다.
return (
<>
{a}
{b}
{c.current}
<input ref={c}/>
<button>a버튼 클릭시 a를 1더한값으로 변경해줌 </button> /*렌더링안됨*/
<button>b버튼 클릭시 b를 1더한값으로 변경해줌 </button> /*렌더링됨*/
<button>c버튼 클릭시 c를 1더한값으로 변경해줌 </button>
<h1>MyComponent</h1>
</>
)
}
초기값인 10들이 출력된다.
버튼 a,b,c 를 누르고, 렌더링이 되면❓
일반변수인 a는 초기값인 10으로 가고,
b와 c는값을 기억
하니까 플러스 1이 되서 11이 된다.
📝 input도 객체니까 .. input에 ref객체를 연결하면 input의 값을 얻어올수있다
const MyComponent = () => {
let c = useRef(null);
//input도 객체니까 .. input에 ref객체를 연결하면 input의 값을 얻어올수있다.
return (
<>
{c.current}
<input ref={c}/>
<button>c버튼 클릭시 c를 1더한값으로 변경해줌 </button>
<h1>MyComponent</h1>
</>
)
}
c.current가 의미하는것은 input 태그 이고,
input 태그안에는 value, checked 가 있다.
그래서 여기서 우리는 checked를 가져와서 볼꺼야
단순하게 한번 해보자 복잡하니깡❗️❗️❗️
refTest.js
//useRef 익혀보기
import React, { useState, useRef } from 'react';
const RefTestComponent = () => {
const [a, setA] = useState(0);
const b = useRef(0);
let c = 0;
const showAll = () => {
console.log('state변수 a: ', a);
console.log('b.current: ', b.current);
console.log('일반 변수 c: ', c);
}
return (
<>
<h1>RefTest Component</h1>
<h2>state변수 a의 값 : {a}</h2>
<button onClick={() => { setA(a + 1) }}>state변수 변경</button>
<button onClick={() => { b.current++; }}>Ref 객체속 current변경</button>
<button onClick={() => { c++ }}>일반변수 변경</button>
<br />
<button onClick={showAll}>변수들 속의 값 보기</button>
</>
);
};
export default RefTestComponent;
변수들 속의 값 보기 버튼 클릭하면 👇
일반변수변경 버튼을 3번 눌렀다. 결과값은 다음과 같다 👇 (re-rendering 되지않음)
Ref 객체속 current변경 버튼을 2번 눌렀다. 결과값은 다음과 같다 👇 (re-rendering은 되지않고 저장은됨)
state변수 변경 버튼을 1번 눌렀다. 결과값은 다음과 같다 👇 (re-rendering 되면서 ❗️값이 바뀜 )
import React, { useState, useRef } from 'react';
const RefTestComponent = () => {
const [a, setA] = useState(0);
const b = useRef(null);
let c = 0;
const showAll = () => {
console.log('state변수 a: ', a);
console.log('b.current: ', b.current.checked);
console.log('일반 변수 c: ', c);
}
return (
<>
<h1>RefTest Component</h1>
<h2>state변수 a의 값 : {a}</h2>
<input
ref={b}
type="checkbox" />
<button onClick={() => { setA(a + 1) }}>state변수 변경</button>
<button onClick={() => { b.current++; }}>Ref 객체속 current변경</button>
<button onClick={() => { c++ }}>일반변수 변경</button>
<br />
<button onClick={showAll}>변수들 속의 값 보기</button>
</>
);
};
export default RefTestComponent;
b.current
에 내가 만든input checkbox
를 볼수있다.
b.current.checked
를 콘솔로 찍어보면,
체크박스를 누를때마다, false, true로 바뀐다.console.log('b.current: ', b.current.checked);
📌 그런데, checkbox가 여러갠데 그럼 어떻게 하면 여러개를 다룰수있을까?
//useRef 익혀보기
import React, { useState, useRef } from 'react';
const RefTestComponent = () => {
const [a, setA] = useState(0);
const b = useRef([]);
let c = 0;
const showAll = () => {
console.log('state변수 a: ', a);
console.log('b.current: ', b.current.checked);
console.log('일반 변수 c: ', c);
}
return (
<>
<h1>RefTest Component</h1>
<h2>state변수 a의 값 : {a}</h2>
<input ref={(el) => { b.current.push(el) }} type="checkbox" />
<input ref={(el) => { b.current.push(el) }} type="checkbox" />
<input ref={(el) => { b.current.push(el) }} type="checkbox" />
<input ref={(el) => { b.current.push(el) }} type="checkbox" />
<input ref={(el) => { b.current.push(el) }} type="checkbox" />
{/* map으로도 가능 */}
<button onClick={() => { setA(a + 1) }}>state변수 변경</button>
<button onClick={() => { b.current++; }}>Ref 객체속 current변경</button>
<button onClick={() => { c++ }}>일반변수 변경</button>
<br />
<button onClick={showAll}>변수들 속의 값 보기</button>
</>
);
};
export default RefTestComponent;
b.current.checked
를 출력해보면? input tag 6 개가 있는것을 알수있다. 👇console.log('b.current: ', b.current.checked);
const ref객체이름 = useRef(null);
<h1 ref={ref객체이름}>안녕</h1>
👉👉 ref객체이름.current에는 h1태그 객체가 들어가있다.
<h1>안녕</h1>
const ref객체이름 = useRef([]); // ref객체이름.current = [] // 비어있는 배열
<h1 ref={(el)=>{ref객체이름.current.push(el)}}>안녕</h1> <p ref={(el)=>{ref객체이름.current.push(el)}}>반가워</p> <input ref={(el)=>{ref객체이름.current.push(el)}}/>
👉👉 ref 객체이름.current에는
[<h1>안녕</h1>, <p>반가워</p>, <input/>]
가 들어있다.
//차라리 전체 체크 되었다 아니다 이분법적인것보다
//개별적으로 체크된 요소의 id를 배열에 담아서 express한테 보내서 삭제하도록
//rendering 할떄 배열안에 있는 행을 그릴때는 체크된채로,
//배열안에 없는 행을 그릴때는 체크가 안된채로 그린다.
const [checkedRowId, setCheckedRowId] = useState([]); //체크된 행의 id를 담을 배열. 처음에는 빈배열 (체크된게없음 아직)
//개별적으로 체크했을떄
const onSelect = (e, id) => {
// console.log(e.target.checked);
// console.log(id);
//배열에 id를 추가
setCheckedRowId([...checkedRowId, id]); //기존에 배열에 추가한 id를 넣어줘
}
return (
<tbody>
{careerList.map((e) => <tr key={e.id}>
<td><input
type="checkbox"
checked={checkedRowId.includes(e.id)}
onChange={() => onSelect(e.id)}
/>
</td>
</tr>)}
</tbody>
)
}
export default CareerViewTable;
includes() 메서드는 문자열에 다른 문자열이 포함되어 있는지 여부를 확인합니다.(배열이 특정 요소를 포함하고 있는지 확인하는 메서드)
let fruits = ['apple', 'banana', 'orange', 'grape']; console.log(fruits.includes('banana')); // true console.log(fruits.includes('kiwi')); // false
checked={checkedRowId.includes(e.id)}
id가 checked되면 true로 되어서 check가됨
🔎 그런데 check 를 해제했을때도 unchecked가 되야되는데..
const [checkedRowId, setCheckedRowId] = useState([]); //체크된 행의 id를 담을 배열. 처음에는 빈배열 (체크된게없음 아직)
//개별적으로 체크했을떄
const onSelect = (e, id) => {
// console.log(e.target.checked);
// console.log(id);
//🌟 체크가 되었으면 배열에 id를 추가
//체크가 해제되었으면 배열에서 id를 제거
if (e.target.checked) {
//배열에 id를 추가
setCheckedRowId([...checkedRowId, id]); //기존에 배열에 추가한 id를 넣어줘
} else {
//🌟 배열에서 id를 제거
let newCheckedRowId = checkedRowId.filter((e) => e !== id);
setCheckedRowId(newCheckedRowId);
}
}
return (
<tbody>
{careerList.map((e) => <tr key={e.id}>
<td><input
type="checkbox"
checked={checkedRowId.includes(e.id)}
onChange={(event) => onSelect(event, e.id)}
/>
</td>
</tr>)}
</tbody>
)
}
export default CareerViewTable;
const onSelectedAll = (e) => {
// console.log(e.target.checked);
// setIsSelectAll(e.target.checked);
if (e.target.checked) { //전체선택이 되었으면
setCheckedRowId(careerList.map((e) => e.id));
setIsSelectAll(true); //🌟 ture 일때
} else { //체크 해제되어 실행된다면
setCheckedRowId([]);//배열을 비워준다.
setIsSelectAll(false);//🌟 false 일때
}
console.log(isSelectAll);
}
return(
<tr>
<th onChange={onSelectedAll} rowSpan={2}>회사명(활동)</th>
<th rowSpan={2}>직책(활동내용)</th>
<th colSpan={2}>활동 일자</th>
</tr>
<thead>
<tr>
<th>
<input
onChange={onSelectedAll}
type="checkbox"
checked={isSelectAll}
/>
</th>
<th>회사명</th>
<th>직책</th>
<th>일자</th>
<th onClick={deleteAll}><DeleteSweepIcon /></th>
</tr>
</thead>
)
const deleteAll = () => {
//체크된 행의 id를 가지고 express한테 삭제 요청
// let res = await axios.delete('/api/career', { data: { id: checkedRowId } });
checkedRowId.forEach(async (id) => { //삭제가 다섯번 반복이 된다
try {
await axios.delete('/api/career', { data: { id: checkedRowId } })
//첫번째 방법. setCareerList(careerList.filter((e) => (e.id !== id))) //이렇게하면 한번에 마지막 상태를 1번 삭제해준다.
setCareerList((cl) => { return cl.filter((e) => e<.id !== id) });
//2번쨰 방벙. 그때그때마다 삭제해주고 state변수 바뀌었으니 다시 리렌더링 하고. 데이터가 좀더 느리다는 단점이 있다.
alert('삭제 완료!')
} catch (err) {
console.log(err)
alert('삭제 하는 도중 문제가 발생하였습니다. ');
}
});
}
return(
<>
<th>회사명</th>
<th>직책</th>
<th>일자</th>
<th onClick={deleteAll}><DeleteSweepIcon /></th>
</>
)
}
삭제한번에 변경하기
반복횟수만큼
filter()함수
를 써야한다.
효율적이지 않기 때문에,반복문 forloop
사용
const deleteAll = async () => {
//기본 careerList 에서 삭제한 요소들을 제외한 배열 만들기
//체크된 행의 id를 가지고 express한테 삭제 요청
// let res = await axios.delete('/api/career', { data: { id: checkedRowId } });
let cpy = careerList;
try {
for (let i = 0; i < checkedRowId.length; i++) {//삭제가 다섯번 반복이 된다
let id = checkedRowId[i];
await axios.delete('/api/career', { data: { id: checkedRowId } })
cpy = cpy.filter((row) => row.id !== id);
//첫번째 방법. setCareerList(careerList.filter((e) => (e.id !== id))) //이렇게하면 한번에 마지막 상태를 1번 삭제해준다.
// setCareerList((cl) => { return cl.filter((e) => e.id !== id) });
//2번쨰 방벙. 그때그때마다 삭제해주고 state변수 바뀌었으니 다시 리렌더링 하고. 데이터가 좀더 느리다는 단점이 있다.
}
setCareerList(cpy); //두번째 반복이 다 끝나면, setCareerList(cpy)로 "한번"에 마지막 상태를 5번 삭제해준다.
} catch (err) {
console.log(err)
alert('삭제 하는 도중 문제가 발생하였습니다. ');
}
}