컴포넌트 반복

Posted by yunki kim on June 28, 2021

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React from 'react';
 
const IterationSample = () => {
    return(
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
        </ul>
    );
};
 
export default IterationSample;
cs

  위와같은 코드가 있다고 해보자. li가 중복되어 있다. 만약 이런 식으로 중복된 코드가 늘어날 경우 파일 용량 증가와 효율적인 관리가 불가능 하다. 이럴때는 map()을 사용하면 된다

1
2
3
4
5
6
7
8
9
import React from 'react';
 
const IterationSample = () => {
    const names = ['1''2''3'];
    const name_list = names.map(name => <li>{name}</li>)
    return <ul>{name_list}</ul>
};
 
export default IterationSample;
cs

  하지만 이렇게 하면 다음과 같은 에러가 발생한다.

key

 리엑트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내기 위해 사용한다. 유동적인 데이터를 CRUD할때 key가 없다면 virtual DOM에서 리스트를 순차적으로 비교 한다. 하지만 key가 있다면 이를 사용해 좀 더 빠르게 어떤 변화가 일어 났는지 알 수 있다.

  key값 설정은 props를 설정하는것 처럼 map내부에서 설정해 주면 된다. key값을 유일해야하기 때문에 데이터가 가진 고유의 값을 key값으로 설정한다.

1
2
3
4
5
6
7
const articleList = articles.map(article => (
    <Article
        title={article.title}
        writer={article.writer}
        key={article.id}
    />
);
cs

  하지만 위와 같이 고유 번호가 없을 경우 map함수에 전달되는 콜백 함수의 인수인 index값을 사용하면 된다. 하지만 index를 key로 사용하면 배열이 변경 되었을때 효율적으로 리렌더링이 되지 못하므로 고유한 값이 없을때만 사용해야 한다.

1
2
3
4
5
6
7
8
9
import React from 'react';
 
const IterationSample = () => {
    const names = ['1''2''3'];
    const name_list = names.map((name, idx) => <li key={idx}>{name}</li>)
    return <ul>{name_list}</ul>
};
 
export default IterationSample;
cs

 

데이터 추가

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
import React, {useState} from 'react';
 
const IterationSample = () => {
    const [names, setNames] = useState([
        {id: 1, text: 'a'},
        {id: 2, text: 'b'},
        {id: 3, text: 'c'},
        {id: 4, text: 'd'},
    ]);
    const [input_text, setInputText] = useState('');
    const [next_id, setNextId] = useState(5);
    const onChange = (e) => setInputText(e.target.value);
    const onClick = () => {
        const next_name = names.concat({
            id: next_id,
            text: input_text,
        });
        setNextId(next_id + 1);//next_id값 1 증가
        setNames(next_name);//name 값을 업데이트 한다
        setInputText('');//text를 비운다
    }
    const name_list = names.map(name => <li key={name.id}>{name.text}</li>);
    return(
        <div>
            <input value={input_text} onChange={onChange}/>
            <button onClick={onClick}>add</button>
            <ul>{name_list}</ul>
        </div>
    );
};
 
export default IterationSample;
cs

  위 코드를 보면 새항목을 추가 할때 push가 아닌 concat을 사용했다. push를 사용하면 기존 배열 자체를 변경하지만 concat은 새로운 배열을 만들어 준다. 리엑트에서 상태를 업데이트 할때는 기존 상태를 그대로 두고 새로운 값을 상태로 설정해야 한다. 이를 불변성 유지 라고 하며 이를 적용 해야 나중에 리액트 컴포넌트의 성능을 최적화할 수 있다.

 

데이터 제거

  데이터를 제거할때는 filter()를 사용한다.

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
import React, {useState} from 'react';
 
const IterationSample = () => {
    const [names, setNames] = useState([
        {id: 1, text: 'a'},
        {id: 2, text: 'b'},
        {id: 3, text: 'c'},
        {id: 4, text: 'd'},
    ]);
    const [input_text, setInputText] = useState('');
    const [next_id, setNextId] = useState(5);
    const onChange = (e) => setInputText(e.target.value);
    const onClick = () => {
        const next_name = names.concat({
            id: next_id,
            text: input_text,
        });
        setNextId(next_id + 1);//next_id값 1 증가
        setNames(next_name);//name 값을 업데이트 한다
        setInputText('');//text를 비운다
    }
    const onRemove = (id) => {
        const next_name = names.filter((name=> name.id !== id);
        setNames(next_name);
    }
    const name_list = names.map(name => (
        <li key={name.id} onDoubleClick={() => onRemove(name.id)}>
            {name.text}
        </li>
    ));
    return(
        <div>
            <input value={input_text} onChange={onChange}/>
            <button onClick={onClick}>add</button>
            <ul>{name_list}</ul>
        </div>
    );
};
 
export default IterationSample;
cs