State 끌어올리기
React에서는 기본적으로 하향식 데이터 흐름을 추천한다. 상위 컴포넌트에서 state를 관리하고, 하위 컴포넌트에서는 전달된 props를 처리하도록 한다. 그런데 동일한 데이터를 여러 컴포넌트에서 사용하고, 변경됐을 때 바로 반영되어야 한다면 공통된 상위 컴포넌트에서 state를 처리하고, 하위 컴포넌트에서는 상위로 전달하는 방법을 사용해야 한다. React에서는 이 방법을 state 끌어올리기라고 한다.
내가 React로 만든 component들은 아래와 같았다.
선택된 키워드를 모든 컴포넌트에서 공유해야 했다.
처음에는 여러 컴포넌트에 useState로 selectedKeywords를 정의해줬다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
// App.js
const [selectedKeywords, setKeyword] = useState([]);
// Category.js
const [selectedKeywords, setKeyword] = useState([]);
//카테고리에서 선택/해제한 경우
function handleClick(e) {
const id = e.target.id;
const checked = e.target.checked;
if(checked) {
// 체크된 경우
setKeyword(prevList => [...prevList, id]);
} else {
// 해제한 경우
setKeyword(selectedKeywords.filter(keyword => keyword !== id));
}
}
useEffect(() => {
// selectedKeywords 가 변할 때 마다 props.onChange 실행해 App에 배열을 넘김
props.onChange(selectedKeywords);
}, [selectedKeywords, props]);
// keywordLists.js
let keywords = props.selectedKeywords;
|
cs |
App.js와 Category.js에서 따로 state를 만들고, category에서 키워드를 변경하면 useEffect -> props.onChange()로 App으로 전달했다.
App, Category, keywordLists만 있을 땐 원하는 대로 잘 작동했다. 그런데 Result와 Result내의 keywordLists가 추가됐을 때 문제가 생겼다. Result내의 keywordLists에서 키워드를 추가/제거했을 때 제대로 작동하지 않았다.
그래서 props와 state에 대해 알아보다가 reactjs.org에서 state 끌어올리기에 대한 문서를 보게됐다.
공통된 상위 컴포넌트에서 state를 관리하도록 하고, 하위 컴포넌트에서는 state를 가지고있지 않는다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
// App.js
const [selectedKeywords, setKeyword] = useState([]);
return(
// ...
<Category
selectedKeywords={selectedKeywords}
onChange={(newKeywords) => setKeyword(newKeywords)}
></Category>
)
// Category.js
// 이전 코드 : const [selectedKeywords, setKeyword] = useState([]);
let selectedKeywords = props.selectedKeywords
//카테고리에서 선택/해제한 경우
function handleClick(e) {
const id = e.target.id;
const checked = e.target.checked;
if(checked) {
// 체크된 경우
// 이전 코드 : setKeyword(prevList => [...prevList, id]);
props.onChange([...selectedKeywords, id]);
} else {
// 해제한 경우
// 이전 코드 : setKeyword(selectedKeywords.filter(keyword => keyword !== id));
props.onChange(selectedKeywords.filter(keyword => keyword !== id));
}
}
// state를 사용하지 않으니 useEffect도 필요가 없다.
return(
// ...
<KeywordLists
selectedKeywords={selectedKeywords}
onClick={(keywords) => props.onChange(keywords)}
></KeywordLists>
)
// keywordLists.js
let keywords = props.selectedKeywords;
// selectedKeywords가 변할 경우, props.onClick으로 상위컴포넌트에 전달한다
// 제거하는 경우
function handleDelBtn(e) {
let id = e.target.id;
if(id === '') {
id = e.target.parentElement.id;
};
keywords = keywords.filter(keyword => keyword !== id);
props.onClick(keywords);
}
// 추가하는 경우
function handleAddBtn(e){
let id = e.target.id;
if(id === '') {
id = e.target.parentElement.id;
};
props.onClick([...keywords, id]);
}
|
cs |
가장 큰 변화는 Category.js인데, state대신 props.selectedKeywords를 사용하니 setState()가 아닌 props.onChange를 통해 변경된 selectedKeywords를 전달했다. 그 하위 컴포넌트인 KeywordLists도 추가하거나 제거한 새로운 selectedKeywords를 Category로 전달하고, Category는 App.js로 전달한다.
keywordLists 컴포넌트에서 키워드를 새롭게 추가했다면 다음과 같은 경로로 selectedKeywords가 변경된다.
App에서는 전달받은 newKeywords를 setKeywords(newKeywords)로 selectedKeywords를 변경시킨다. App의 state가 변경되었으므로, App이 새로고침되며 하위 컴포넌트들도 새로고침을 통해 selectedKeywords를 전달받아 새로고침하게된다.
Result의 경우는 Result에서는 키워드 선택에 관여하지 않으므로 App과 KeywordLists사이에서 전달하는 역할만 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
// App.js
const [selectedKeywords, setKeyword] = useState([]);
return(
// ...
<Result
selectedKeywords={selectedKeywords}
onChange={(newKeywords) => setKeyword(newKeywords)}
></Result>
)
// Result.js
return(
// ...
<KeywordLists
selectedKeywords={props.selectedKeywords}
onClick={(newKeywords) => props.onChange(newKeywords)}></KeywordLists>
)
|
cs |
전체적으로 만들어진 App은 아래와 같다.
Category, Category내의 KeywordLists, Result내의 KeywordLists 에서 모두 키워드 추가/제거가 가능하고, 선택/해제된 결과가 모든 컴포넌트에 바로 반영된다.
참고한 사이트
https://ko.reactjs.org/docs/lifting-state-up.html
'React' 카테고리의 다른 글
다이어리 검색기 만들기(6) - JSON 데이터 만들기 (0) | 2021.10.27 |
---|---|
React - State 업데이트, 불변성 (0) | 2021.10.15 |
다이어리 검색기 만들기(5) - 재사용 위한 컴포넌트 추출 (0) | 2021.10.11 |
다이어리 검색기 만들기(4) - 선택된 키워드 관리(2) (0) | 2021.10.08 |
다이어리 검색기 만들기(3) - 선택된 키워드 관리 (0) | 2021.10.07 |