리액트는 데이터가 부모 컴포넌트에서 자식 컴포넌트로 단방향(Top to Bottom)으로 흐른다.
만약, 자식 컴포넌트의 어떤 이벤트에 의해 부모 컴포넌트의 상태가 바뀐다면, 역방향으로 데이터가 흐르고 이는 리액트의 단방향 흐름 원칙에 위배되는 것인가?
리액트에서는 단방향 흐름의 원칙을 지키면서, 자식 컴포넌트에서 부모 컴포넌트로 데이터를 보내기 위한 방법(Bottom to Top)으로 상태 끌어올리기라는 방법을 제시한다.
그 방법은 부모 컴포넌트의 상태 변화함수를 자식 컴포넌트에 인자로 전달하고 자식 컴포넌트에서 그 함수를 실행시켜 부모 컴포넌트의 상태를 변화시키는 것이다.
Ex)
ChildComponent onBtnClick = {handleChange}
function ChildComponent({onBtnClick}){}
return <button onCLick = {handleClick}>값 변경</button>
따라서, 정리해보자면, 자식 컴포넌트에서 버튼을 클릭하면 이벤트 핸들러(handleClick)가 실행되는데, 그 핸들러는 자식 컴포넌트가 인자로 입력받은 함수 (콜백함수, 부모 컴포넌트의 상태변화 함수)를 동작시키고, 그 결과 부모 컴포넌트의 상태가 업데이트 된다.
Ex 2)
데이터 흐름
<NewTweetForm onButtonClick = {addNewTweet} />
const addNewTweet = (newTweet) => {strTweets([...tweets,newTweet])}
Bareminimum Test 복습
Main.js
/* ...생략 */
export default function Main() {
// 항공편 검색 조건을 담고 있는 상태
const [condition, setCondition] = useState({
departure: 'ICN',
});
const [flightList, setFlightList] = useState(json);
// 주어진 검색 키워드에 따라 condition 상태를 변경시켜주는 함수
const search = ({ departure, destination }) => {
if (
condition.departure !== departure ||
condition.destination !== destination
) {
console.log('condition 상태를 변경시킵니다');
// TODO: search 함수가 전달 받아온 '항공편 검색 조건' 인자를 condition 상태에 적절하게 담아보세요.
setCondition({departure,destination})
//1. 상태변경 함수인 search에 condition 변경 함수인 setCondition 을 이용해 값을 바꿔준다.
}
};
/* ...생략 */
<main>
<h1>
여행가고 싶을 땐, States Airline
</h1>
<Search onSearch={search}/>
// 2 Search 컴포넌트에는 상태 변경 함수 `search`가 `onSearch` props로 전달되어야 한다
<div className="table">
<div className="row-header">
/* ...생략 */
Search.js
/* ...생략 */
function Search({onSearch}) {
// 3 onSearch props를 받아온다
const [textDestination, setTextDestination] = useState('')
/* ...생략 */
const handleSearchClick = () => {
console.log('검색 버튼을 누르거나, 엔터를 치면 search 함수가 실행됩니다')
// 4 상태 변경 함수 `search`는 Search 컴포넌트의 `검색` 버튼 클릭 시 실행되어야 합니다
// 검색 버튼을 클릭했을때 onChange는 handleChange값이 변경된다고 아래에 적혀있다
// handleChange는 도착지 값이 변경되는 것을 알려주고 있고
// 출발지는 고정하고 도착지의 값을 textDestination으로 변경해주면 된다
// 서치 함수에서 setCondition({departure, destination}) 객체형태로 값을 받아오는걸 알 수 있으니
// 똑같이 값을 넣어줘야 한다
onSearch({departure : "ICN", destination : textDestination})
}