본문 바로가기

react

[리액트를 다루는 기술] 6장 컴포넌트 반복

 

1. 자바스크립트 배열의 map() 함수 

 

- map() 함수를 사용하여 반복되는 컴포넌트를 렌더링할 수 있음

- map 함수는 파라미터로 전달된 함수를 사용해서 배열 내 각 요소를 원하는 규칙에 따라 변환한 후 그 결과로 새로운 배열을 생성 

 

1) 문법

 

arr.map(callback, [thisArg])

 

- 파라미터 

  • callback : 새로운 배열의 요소를 생성하는 함수  

      - currentValue: 현재 처리하고 있는 요소 

      - index: 현재 처리하고 있는 요소의 index 값

      - array : 현재 처리하고 있는 원본 배열

 

  • thisArg(선택항목) : callback 함수 내부에서 사용할 this 레퍼런스 

 

ex)

- 기존 배열에 있는 값들을 제곱하여 새로운 배열 생성

const numbers = [1,2,3,4,5];
const result = numbers.map(num => num * num);
console.log(result);

 

 

 

2. 데이터 배열을 컴포넌트 배열로 변환하기 

 

- 문자열로 구성된 배열을 선언

- 그 배열 값을 사용하여 <li>... </li> JSX 코드로 된 배열을 새로 생성한 후 nameList에 담음

 

lterationSample.js

const IterationSample = () => {
    const names = ['눈사람', '얼음', '눈','바람'];
    const nameList = names.map(name=><li>{name}</li>);
    return <ul>{nameList}</ul>
};

export default IterationSample;

 

 

- "key" prop이 없다는 경고 메시지 표시됨 

 

 

3. Key

 

- 리액트에서 key는 컴포넌트 배열을 렌더링했을 때 어떤 원소에 변동이 있었는지 알아내려고 사용 

- 유동적인 데이터를 다룰 때는 원소를 새로 생성할 수도, 제거할 수도, 수정할 수도 있음

 

1) key 설정

 

- key 값은 항상 유일해야 함

- 데이터가 가진 고윳값을 key 값으로 설정

- 고유 번호가 없을 떄는 map 함수에 전달되는 콜백 험수의 인수인 index 값을 사용

- index 값을 key로 사용하면 리렌더링이 비효율적

 

IterationSample.js

const IterationSample = () => {
    const names = ['눈사람', '얼음', '눈','바람'];
    const nameList = names.map((name,index)=><li key={index}>{name}</li>);
    return <ul>{nameList}</ul>
};

export default IterationSample;

 

 

 

4. 동적인 배열 렌더링 

 

1) 초기 상태 설정하기 

 

- useState를 사용하여 상태 설정

  - 데이터 배열

  - 텍스트를 입력할 수 있는 input의 상태 

  - 데이터 배열에서 새로운 항목을 추가할 때 사용할 고윳값 id를 위한 상태 

 

literationSample.js

import { useState } from 'react';

const IterationSample = () => {
    const [names, setNames] = useState([
        {id:1, text:'눈사람'},
        {id:2, text:'얼음'},
        {id:3, text:'눈'},
        {id:4, text:'바람'}
    ]);
    const [inputText, setInputText] = useState('');
    const [nextid, setNextid] = useState(5); //새로운 항목을 추가할 때 사용할 id

    const namesList = names.map(name=><li key={names.id}>{names.text}</li>);
    return <ul>{namesList}</ul>;
};

export default IterationSample;

 

 

2) 데이터 추가 기능 구현하기 

 

- 새로운 이름을 등록할 수 있는 기능 

- onClick 함수에서는 배열의 내장 함수 concat을 사용하여 새로운 항목을 추가한 배열을 만들고, setNames를 통해 상태 업데이트 

- 리액트에서 상태를 업데이트할 때는 존 상태를 그대로 두면서 새로운 값을 상태로 설정해야 함 (불변성 유지!)

- onClick에서 새로운 항목을 추가할 떄 객체의 id 값은 nextId를 사용하도록 하고, 클릭될떄 마다 값이 1씩 올라가도록 구현 - button이 클릭될 떄 기존의 input 내용을 비우는 것도 구현 

 

IterationSample.js

 

import { useState } from 'react';

const IterationSample = () => {
    const [names, setNames] = useState([
        {id:1, text:'눈사람'},
        {id:2, text:'얼음'},
        {id:3, text:'눈'},
        {id:4, text:'바람'}
    ]);
    const [inputText, setInputText] = useState('');
    const [nextId, setNextId] = useState(5); //새로운 항목을 추가할 때 사용할 id


    const onChange = e => setInputText(e.target.value);

    const onClick = () => {
        const nextNames = names.concat({
            id:nextId, 
            text:inputText
        });
        setNextId(nextId+1); //nextId 값에 1을 더해줌
        setNames(nextNames); //names 값을 업데이트 
        setInputText(''); //inputText를 비움
    }
    const namesList = names.map(name=><li key={names.id}>{names.text}</li>);
    return(
        <>
            <input value={inputText} onChange={onChange} />
            <button onClick={onClick}>추가</button>
            <ul>{namesList}</ul>
        </>
    );
};

export default IterationSample;

 

 

 

3) 데이터 제거 기능 구현하기 

 

- 각 항목을 더블클릭했을 떄 해당 항목이 화면에서 사라지는 기능 

- 불변성을 유지하면서 배열의 특정 항목을 지울 때는 배열의 내장 함수 filter을 사용 

 

- filter 함수를 사용하면 배열에서 특정 조건을 만족하는 원소들만 쉽게 분류할 수 있음 

const numbers = [1,2,3,4,5,6];
const biggerThanThree = numbers.filter(number=>number>3);
//결과 : [4,5,6]

 

- filter 함수를 응용하여 특정 배열에서 특정 원소만 제외시킬 수 있음 

 ex) 3만 없애기 

const numbers = [1,2,3,4,5,6];
const withoutThree = numbers.filter(number=>number !==3);
//결과: [1,2,4,5,6]

 

 

- HTML 요소를 더블클릭할 때 사용하는 이벤트 이름은 onDoubleClick

- onRemove라는 함수를 만들어서 각 li 요소에 이벤트 등록

 

IterationSample.js

 

import { useState } from 'react';

const IterationSample = () => {
    const [names, setNames] = useState([
        {id:1, text:'눈사람'},
        {id:2, text:'얼음'},
        {id:3, text:'눈'},
        {id:4, text:'바람'}
    ]);
    const [inputText, setInputText] = useState('');
    const [nextId, setNextId] = useState(5); //새로운 항목을 추가할 때 사용할 id


    const onChange = e => setInputText(e.target.value);

    const onClick = () => {
        const nextNames = names.concat({
            id:nextId, 
            text:inputText
        });
        setNextId(nextId+1); //nextId 값에 1을 더해줌
        setNames(nextNames); //names 값을 업데이트 
        setInputText(''); //inputText를 비움
    };

    const onRemove = id => {
        const nextNames = names.filter(name=>name.id !== id);
        setNames(nextNames);
    };

    const namesList = names.map(name =>(
    <li key={name.id} onDoubleClick={()=>onRemove(name.id)}>
        {name.text}
    </li>
    ));

    return(
        <>
            <input value={inputText} onChange={onChange} />
            <button onClick={onClick}>추가</button>
            <ul>{namesList}</ul>
        </>
    );
};

export default IterationSample;