리스트와 키(Lists and Keys)
1 2 3 | const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((number) => number * 2); console.log(doubled); | cs |
먼저, 자바스크립트를 리스트로 변환하는 것을 보자
위의 코드를 사용하면 map() 함수를 사용하여 숫자 배열을 가져와서 두배로 늘릴수 있다.
map()에 의해 반환 된 새로운 배열을 double 변수에 할당하고 그것을 기록한다.
따라서 콘솔에는 [2,4,6,8,10]이 출력된다.
리액트에서 엘리먼트를 리스트에 변환하는 것은 이것과 가의 동일하다
여러 컴포넌트 랜더링
1 2 3 4 5 | const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li> ); | cs |
엘리먼트 콜렉션을 빌드하고 중괄호 {}를 사용하여 JSX에 포함이 가능하다.
위의 예제 코드에서는 자바스크립트 map() 함수를 사용하여 숫자 배열을 반복한다.
각 항목에 대해 <li> 요소를 반환하고, 엘리멘트 배열을 listitem에 할당한다
1 2 3 4 | ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') ); | cs |
이렇게 반환된 listitem 배열을 <ul> 태그 안에 넣고 DOM에 랜더링한다.
결과적으로 위의 코드는, 실행되면 1과 5 사이의 숫자로 된 글 머리표 목록을 표시한다.
기본적인 리스트 컴포넌트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li>{number}</li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); | cs |
우리는 앞의 예제에서 숫자를 허용하고 정렬되지 않은 엘리먼트 목록을 출력하는 컴포넌트로 리팩토링 할 수 있다.
이 코드를 실행하면 엘리먼트 목록에 키가 제공되어야한다는 경고가 표시된다.
키는 엘리먼트 목록을 만들 때 포함해야하는 특수 문자열 속성이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); | cs |
numbers.map() 내부의 키를 지정하여 에러가 난 문제 코드를 수정하자.
키(Key)
1 2 3 4 5 6 | const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); | cs |
키는 리액트가 아이템의 변경사항, 추가, 제거를 식별할 수 있도록 도움을 준다.
엘리먼트에 안정적인 ID를 제공하려면 배열 내부 엘리먼트에 키를 지정해야합니다.
1 2 3 4 5 | const todoItems = todos.map((todo) => <li key={todo.id}> {todo.text} </li> ); | cs |
키를 선택하는 가장 좋은 방법은 형제 중 리스트를 고유하게 식별하는 문자열을 사용하는 것이다.
대부분의 경우 데이터의 ID를 키로 사용한다.
1 2 3 4 5 6 | const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> ); | cs |
랜더링 된 항목에 대한 안정적인 ID를 설정할 수 없는 경우,
최후의 수단으로 색인을 키로 사용할 수 있다.
키로 컴포넌트 추출
키는 배열의 컨텍스트 내부에서만 의미를 가진다
예를 들어, 아래의 코드에서 ListItem 컴포넌트를 추출하는 경우,
ListItem 자체의 루트 <li> 요소가 아니라 배열의 <ListItem /> 엘리먼트에 키를 보관해야한다.
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 | function ListItem(props) { const value = props.value; return ( // Wrong! There is no need to specify the key here: <li key={value.toString()}> {value} </li> ); } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Wrong! The key should have been specified here: <ListItem value={number} /> ); return ( <ul> {listItems} </ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); | cs |
위의 예제는 잘못된 key 사용 방법이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | function ListItem(props) { // Correct! There is no need to specify the key here: return <li>{props.value}</li>; } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Correct! Key should be specified inside the array. <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); | cs |
위의 예제는 올바른 key 사용 방법이다.
즉, map 함수 내부에서 key를 포함해 전달해 줘야한다.
키는 동일한 컴포넌트들 사이에서 유일성을 가져야한다.
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 | function Blog(props) { const sidebar = ( <ul> {props.posts.map((post) => <li key={post.id}> {post.title} </li> )} </ul> ); const content = props.posts.map((post) => <div key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> </div> ); return ( <div> {sidebar} <hr /> {content} </div> ); } const posts = [ {id: 1, title: 'Hello World', content: 'Welcome to learning React!'}, {id: 2, title: 'Installation', content: 'You can install React from npm.'} ]; ReactDOM.render( <Blog posts={posts} />, document.getElementById('root') ); | cs |
배열내에서 사용하는 키는 유일해야한다.
그러나 전역적으로 유일성을 가질 필요는 없다.
두개의 다른 배열을 생성할 때 동일한 키를 사용할 수 있다.
1 2 3 4 5 6 | const content = posts.map((post) => <Post key={post.id} id={post.id} title={post.title} /> ); | cs |
키는 리액트에서 힌트 역할을 하지만 컴포넌트 엘리먼트로 전달되지는 않는다.
컴포넌트에 동일한 값이 필요하면 명시적으로 다른 이름의 props로 전달해야한다.
예를 들어, 위의 예에서 id 값을 읽을 수 있지만, key값은 읽을 수 없다.
JSX에서 map() 사용하기
1 2 3 4 5 6 7 8 9 10 11 12 | function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <ListItem key={number.toString()} value={number} /> ); return ( <ul> {listItems} </ul> ); } | cs |
위의 예제에서 우리는 별도의 listitems 변수를 선언하고 이를 JSX에 포함시켰다.
1 2 3 4 5 6 7 8 9 10 11 | function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); } | cs |
JSX는 map()의 결과를 인라인으로 표현 할 수 있도록 모든 expression을 중괄호 내에 표현할 수 있다.
상황에 따라 이 코드가 명확해 질 수 있지만 스타일이 악용될 수 있다.
자바스크립트와 마찬가지로 가독성을 위해 변수를 추출할 가치가 있는지는 개발자가 결정해야한다.
map() 함수가 너무 중첩되어있으면 마찬가지로, 컴포넌트를 분리하는 것이 좋다.
'개발' 카테고리의 다른 글
[ReactJS] State 끌어 올리기(Lifting State Up) (0) | 2017.06.13 |
---|---|
[ReactJS] 입력폼(Forms) (0) | 2017.06.13 |
[ReactJS] 조건부 랜더링(Conditional Rendering) (0) | 2017.06.13 |
[ReactJS] 이벤트 핸들링(Event Handling) (0) | 2017.06.13 |
[ReactJS] State와 라이프 사이클 (0) | 2017.06.13 |
댓글