5일에 걸쳐 작성한 리액트 basic concept !!
처음엔 understand가 거~의 없었다
계속 강의 재복습하면서 그냥 감각이 잡힐때까지 반복
habit-tracker 앱 복습
최상위 INDEX.JS에서는 APP.JSX를 그리고
APP.JSX에서는 최종적으로는 컴포넌트로 바꾸고
NAVBAR와 HABITS 자식 컴포넌트 2개를 그린다
일단 HABIT이라는 컴포넌트부터 만들고 이 HABIT을 HABITS안에 그려줄건데
li에 들어갈 부분을 정적으로 html구현을 한다고 생각을 하고
이름 숫자 플러스버튼 마이너스 버튼 삭제버튼 이렇게 한줄이니까
habit에서 <span className=해서 이름넣고 등등등 했음
css까지 스타일 다 잡고나서 플러스버튼 누르면 올라가고 하는 이벤트를 잡을건데
데이터를 따졌을때 이 한줄li에서 데이터라고 볼수있는건숫자부분 한개임
플러스를 몇번했느냐? ->이 부분을 state 오브젝트로 만들건데
state = {
count: 0;
}
자 이제 그럼 저 숫자 jsx로 만들어낸거에는 일반숫자를 표기하는게 아니라 {}써서 로직으로 나타내야함
class로 만들었으니까 this.state.count 이렇게 해주고
클릭하면 뭐가 나올려면 onClick이 불려야하니까
button태그안에 onclick={this.handleIncrement} ->클릭하면handleIncrement라는 콜백함수를 부르라는 거지
그러면 handleIncrement를 정의하는데
this.setState({}) 이 함수를 써줘야 state가 변경이 된다
화살표함수써서 이 함수는 1씩 증가시키는거니까 count: this.state.count + 1 이렇게
handleDecrement는 마이너스되는거 방지하려면
const count = this.stae.count -1; 1씩 감소한다는 변수를 지정하고
this.setState로 제어문 ? : 넣기 -> count: count < 0 ? 0 : count
즉 카운트는 0보다 작으면 0으로 나오고 아니면 그냥 1씩 감소하라는거
*props속성은 매개변수처럼 컴포넌트 밖에서 정의된거고
*state는 함수내에서 정의된 변수처럼 컴포넌트 안에서 정의된거
이렇게하고 이거를 habits라는 컴포넌트를 만들어서 이 안에 그려줄건데
state에 habits 배열을 만들거
왜냐면 일단 동적으로 눈에보이는 li 3개를 플러스 마이너스 누르면서 동작시킬거
이름 카운트 해서 배열만들고
render에 ul 의미있는 태그로 묶어주고
this.state.habits에 map(배열순회)
이거를 map(habit => ( <Habit /> )) 이렇게
그니까 Habit 컴포넌트를 li한줄 그린거를 반복할거니까
각각의 habit이 새로운 배열로 반환이 되는거
화살표함수는 habit이라는 오브젝트를 Habit컴포넌트로 변환한다는거
근데 이걸 prop으로 넘겨야
habit에서 li작성한 이름을 동적으로 나타낼거아니야
map(habit => ( <Habit /> )) 이부분을
map(habit => ( <Habit habit={habit} /> ))
habit은 prop이름 즉 속성명이 되는거지 {}안에들어가는건 전달해줄 데이터
이렇게 ul 안에 li
자식요소가 있으면 얘네 고유한 key 아이디값을 주는게중요하다
이걸 임의로 일단 habits 배열안에 id값 기입하고
map돌리는거 안에 props 앞에 key={habit.id} 이렇게 해줌
Habit은 부모에서 받은 속성만 사용하여 보여주는 컴포넌트라
state가 필요없어져서 기입했던거 삭제함
핸들링로직도 이름만 남겨두고 비워두고
habit 컴포넌트를 콜백함수만 호출해주는 함수로 만들기
이 Habits 컴포넌트안에 Habit 그릴때
habit을 prop으로 넘긴거 옆에 증가하는 함수를 prop으로 또 넘겨줌
이렇게하고 Habit에도 props 심어줘야하니까
비워둔 로직안에 this.prop.onIncrement(this.props.habit)
증가는 spread operator로 새 배열껍데기 만들어서
인덱스해서 추가해주고 setstate
자 이제 왜 app 즉 최상위에 state를 업데이트했느냐
왜 컴포넌트로 바꿔놨느냐
왜냐면 navnar컴포넌트에서도 state를 써야하기때문이다
그러면 최상위에 state를 해놓으면 navbar던 habits이던 다 같이 쓸수있으니까
app을 클래스로 바꿔주고
Habits에있던 state c+x하고
핸들링로직들 복사해서 가져오고
그러면 얘네도 마찬가지로 Habit에 한거처럼
로직들안에 내용을 this.props.onIncrement(habit)으로 전부 바꿔줌
자 이제 Habits 에 데이터는 없고
prop에 전달된 습관들 배열을 map 돌면서
Habit이라는 컴포넌트로 변경해서 보여주는 역할
굳이 꼽아 말하자면 지금
Habit 에는 li태그안에 span이렇게 감싸져있고
Habits에는 ul태그안에 <Habits />해서 프롭들 심어놓음 근데
이거를 {}괄호안에 해서 this.props.habits.map()해준거
이제 navbar컴포넌트 만들거
nav안에 로고랑 이름이랑 카운트
이 카운트 사이에 {}해서 this.props.totalCount
당연히 이거 app가서 navbar 심어준거 옆에 속성으로 심어줘야겠지
totalCount={this.state.habits.filter 하는데
이게 뭐냐면 아이템 카운트가 0이상인 아이들을 골라서
걔네의 length 즉 갯수를 나타내라는거
이제 addForm만들거
HabitAddForm이라는 컴포넌트 생성
form태그로 묶어주고
안에 input, button 추가
이제 이 폼은 Habits 맨위에 그릴꺼니까
Habits가서 HabitAddForm 그려줌
자 이제 다시 폼으로 돌아와서
이 폼을 누르면 submit이 되면 추가가 되는걸 그릴건데
이 form태그 안에 onSubmit해주고 위에 변수 작성해줌
submit은 preventdefault해줘야하니까 해주고
이 input에 입력된 데이터를 알아와야지 그려낼수있으니까
inputRef = React.createRef():해주고 원하는요소에 ref={"this.inputRef"} 전달해줌
즉 input에.
자 그러면 onSubmit 에
이거의 값 즉 this.inputRef.current.value 를
name 이라는 변수에 할당하고
이 name이 있다면 props onAdd라는 함수에 이름을 전달해줄거
-> name && this.props.onAdd(name);
자 우리가 onAdd를 속성명으로 기입한적 없으니
그려준 곳 Habits에 가서
HabitAddForm 꺽쇠안에 속성명 onAdd 적어주고 this.handleAdd
그러고 handleAdd 정의해주는데
this.props.onAdd(name)
이제 app에 그려줘야하는데
Habits에 onAdd 속성명 추가해주고
여기의 handleAdd정의에는
name을화살표함수로 받아서
spread operator 로 새로운 배열껍데기를 만들어줌
그리고 setstate로 업데이트해줌
이 배열을 새롭게만들어서 추가해주는거
그니까 맨첨에 추가할때도 배열로 만들어서 넣었잖아
내가 인풋에 입력한거 초기화하는거는
HabitAddForm에가서 this.inputRef.current.value = ''; 막줄에 추가해주거나
formRef도 createRef 해주고 ref도 form태그 그린거에 심어주고 this.formRef.current.reset();해줘도 됨
남은건 리셋버튼인데 이건 굳이 컴포넌트 따로 안만들고 Habits안에 태그로 만들거
그 태그안에 onClick되면 this.props.onReset
자 그럼 app 으로와서
handleReset 정의
Habits그려놓은 태그안에
onReset={this.handleReset} 해줌
handleReset은 map으로 배열을 빙글빙글 돌려서
카운트를 0으로 만들고 habit을 리턴
그리고 setState
--------------------------------------------------------------------------------
성능 분석을 할건데 렌더함수에 로그 출력해둬서
렌더가 함수가 언제 호출되는지 확인을 해볼거
지금 인풋에 새로운걸 입력하면 전부다 출력됨
이건 state가 변해서 자식요소들이 업데이트되니까
render함수가 호출되는거라 이해감
근데 플러스버튼이나 그런걸 클릭하면 전부다 호출됨
근데 리액트는 버추얼돔에서 자기가 실질적으로 업데이트될걸
비교해서 업데이트하는데 그걸 elements에서 깜빡이고 사라지는걸로 확인가능
근데 이거를 컴포넌츠 툴에서 (숨겨진ㅎㅎ) 설정눌러서
hightlight updates 체크박스 해주면 화면 자체에서 확인가능
이렇게 업데이트될거만 할수있게하는게 purecomponent와 memo
얘네는 state,props에 변화가 없으면 렌더함수 호출x
자 input 이 변화될 일이 없잖아
HabitAddForm가서 purecomponent로 바꿔주면이제 불필요한 렌더링 하지않음
---------------------------------------------------------------------------------------------
리액트 훅
= 함수형컴포넌트에서도 state, lifecycle 사용가능
state는 const [count, setCount] = useState(0); (0은 초기값)
핸들링이벤트
const handleIncrement = () => {
setCount(count: count + 1);
};
중요한점은 클래스는 이런 멤버변수들은 클래스가 만들어질때 딱 한번만 만들어지고
state가 변경되거나 prop이 업데이트되면 render함수만 반복해서 호출이 되는데
함수형컴포넌트는 함수기때문에 변경이 되면 전부 다 호출이됨
리액트훅에서는
createRef말고 useRef를 사용
한번만 만들고 메모리에 저장해놓고 다시 재사용
useCallback을 쓰면 동일한 콜백함수만 전달
useEffect는
componentDidMount + componentDidUpdate를 결합한 아이
처음 컴포넌트가 업데이트 되었을때만 사용하려면
useEffect(()=>{
console.log(~);
}, []);
카운트가 변경되었을때마다 함수호출
useEffect(()=>{
console.log(~);
}, [count]);
'코딩 > 리액트' 카테고리의 다른 글
리액트 / 3주차 공부 노트 / 코딩애플 (0) | 2022.05.01 |
---|---|
리액트 / 2주차 강의 노트 / Youtube clone coding (0) | 2022.04.24 |
배포하기 github, netlify (0) | 2022.04.19 |
리액트 / 개념과 툴 정리 (터미널, node.js, npm, yarn) (0) | 2022.04.15 |
리액트 / 강의 선택과 노션사용 (0) | 2022.04.14 |