다중 state 해결
- 자 앞서 배운것을 토대로 1개의 component에 여러가지 state를 작성해보았다.
하지만 이건 5살 짱구가봐도 이상한 코드이다. 그래서 이 코드를 한개로 합쳐보겠다.
- 하지만 그전에 왜
useState()
함수가 input 값이 amount와 date인 int,date type임에도 string으로 초기화했냐고 물어봤다면 아주 훌륭한 관찰능력을 갖고있다.
왜냐면 event.target.value를 가져오면 type이 string이기 때문에 초기값을 string type으로 설정했다.
-
정답은 바로 JS객체를 이용하는 것이다.
단, 전과의 차이점은 이 state를 업데이트 할때마다 3개가 한큐에 업데이트 해야한다는 뜻이다.
-
무슨 뜻이냐~ 만약 당신이 title을 update하는 코드를 작성해따면 반드시 나머지 2개의 property도 적어줘야지, 안 그러면 나머지 2값들을 버리는 것과같기에 원하는 결과가 안 나온다는 뜻이다.
-
하지만 위와같이 객체를 업데이트하는 것은 위엄하다 왜냐하면
지금 우리는 이전 state에 따라 상태를 업데이트하고 있다. 문제는 3개의 값에 1개의 state를 적용하고 있다는 뜻이다. 그러면 다른 값을 잃어버릴 소요가 있다. 그렇다면 또 어떻게 해야할까
const StatePrev = () => {
const [count, setCount] = useState(0);
const onClickCount = () => {
setCount((count) => count + 1);
setCount((count) => count + 1);
setCount((count) => count + 1);
setCount((count) => count + 1);
};
return (
<div>
<div>현재카운트:{count}</div>
<button onClick={onClickCount}>카운트 올리기</button>
</div>
);
};
- prevState 객체를 이용해야한다. prevState는 가장 최신 상태의 snapshot으로 항상 최신의 상태를 업데이트 해둔다. 무슨말이냐
리액트가 상태 업데이트 스케줄을 갖고있기에 바로 실행하지 않는데
그렇다면 동시에 수많은 상태 업데이트를 한다면 오래되었거나 잘못된 상태의 state에 의존할 수 있다.
즉, 만약 당신의 업데이트가 이전상태에 의존한다면 위와같은 방식을 꼭 인지하고있어야한다.
two-way binding
초기화하기
- 우리가 입력을 한 후 내용이 초기화가 되어야하는데 이거는 어떻게 할까?
바로 양방향 바인딩을 통하여 할 수 있다.
- 변경되는 입력값만 수신하는 것이 아니라 입력해서 새로운 값을 다시 전달할 수도 있다는 것이다.
방법
- 간단하다 그냥 component에 value property를 넣어주면 된다.
이는 새로운 값으로 설정할 수 있도록 도와준다.
상태를 업데이트하기위해 입력에서 변경사항을 수신하는 것 뿐만아니라 입력에 상태를 다시 보내주기도 한다.
부=>자
- 앞서 우리가 배웠던 props객체를 이용하여 data를 내릴 수 있다.
자=>부 (Lifting State Up)
- 사실 우리가 two-way binding을 배우는 이유는 바로 자식component에서 부모 component로 보내기위함이었다.
- 그런데 이는 어렵지 않다.
방법
- 얘도 그냥 부모 component에서 data를 끌어낼 수 있는 사용자 지정 property를 만들어서 내려주면 된다.
이때 규칙이 있다.
- 중간 component는 절대 건너뛸 수 없다.
- 사용자 지정 property(method)는 통상
on
접두어가 붙는다.
- 여기 위 사진을 보면 앞서 포스팅했듯 onClick 함수는 사실 JS기본이 아니라 react에 종속되어있던것을 알 수 있었다.
그래서 여기서 단서를 알 수있듯 우리가 가진 컴포넌트에도 복제할 수 있는 패턴이다.
바로 다음과 같이
- 우선 15줄을 보면 ExpenseForm이라는 자식 component에게 data를 넘겼다. 이때 이름은 on접두어가 붙어있다.
- 그럼 자식 요소에서는 props로 받아와서 props 안에있는
saveExpenseDataHandler
를 실행시켜 매개변수를 담아서 보내준다.
- 순차적으로 리액트 스케쥴을 마치고 되돌아온
saveExpenseDataHandler
함수에 다시 매개변수로 들어가서 qeury문을 마치고 다시 App.js로부터 받은 props의 메서드에 매개변수로 data를 담아서 올린다.
- 즉 sibling끼리의 data 교환은 안되고 data를 생성하는 component와 data가 필요한 component에 반드시 공통의 부모요소까지 가서 data 교환이 이루어져야한다. 이는 반드시 App.js일 필요는 없다.