티스토리 뷰

React.js

5. 컴포넌트 반복

JadeStone 2023. 1. 16. 18:16
  1. 목록 요소들을 반복처리 할때는 map함수를 이용 합니다.
  2. 반복 컴포넌트에는 반드시 key props를 전달해야 합니다. ★

 

map함수는 실행한 결과를 가지고 새로운 배열을 만들 때 사용

array.map(callbackFunction(currenValue, index, array), thisArg) 
  • currenValue: 현재값
  • index: 현재인덱스
  • arrayt: 현재배열,
  • thisArg: callbackFunction 내에서 this로 사용될 값
const IterationComponent = () => {

    const arr = [1,2,3,4,5];
    const newArr = arr.map( item => item*10 ) // => 한줄일 경우 리턴

    console.log('map으로 생롭게 만들어진 newArr', newArr)
	
    return (
    	....
    )
}

 

map의 콜백함수의 리턴에 반복시킬 태그를 넣습니다.

리액트에서 key는 배열을 렌더링 시킬때 빠르게 변화를 감지하기 위해 사용하는 속성입니다.

key는 index대신 고유한 값을 넣어 주도록 권유 됩니다. (key를 넣지 않으면 props에러가 발생 됩니다.)

 

const IterationComponent = () => {

    const arr = [1,2,3,4,5];
    const newArr = arr.map((item, index) => <li key={index}>{item}</li>)

    return (
        <ul>
            {newArr}
        </ul>
    )
}

export default IterationComponent;

 

* 수업 중 확인해본 코드


const IterationComponent = () => {

    //1. 반복처리
    const arr = [1,2,3,4,5];
    /*
    const newArr = arr.map(function(item, index, arr){
        return item * 10;
    })
    */
    // const newArr = arr.map((item, index, arr) => item * 10);
    // console.log(newArr);

    //2. 반복처리 (태그)
    //리액트에서 반복처리시에 key를 태그에 작성합니다 (key는 고유한 값입니다)
    //key는 화면에서 렌더링할 때 변화를 감지하기 위해 참조하는 값입니다.
    const newArr = arr.map((item, index) => <li key={index}>{item}</li>);
    console.log(newArr);

    return(

        <>
            <ul>
                {newArr}
            </ul>
        </>

    )

}

export default IterationComponent;

 

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

반복할 요소를 state에 넣고 처리하기

버튼 클릭시 인풋state의 값을 목록state에 추가하기

1. 반복처리할 state선언
2. input state, 인풋 핸들러선언
3. 버튼 클릭시 input state의 값을 목록state에 추가
import { useState } from "react";


const IterationComponent2 = () => {

    //1. 반복처리할 데이터 state
    const data = [{id:1, topic: 'hello'},
                  {id:2, topic: 'bye'} 
                 ];
    const [list, setList] = useState(data)
    const newData = list.map( item => <li key={item.id}>{item.topic}</li> )

    //2.인풋핸들러추가
    const [inputData, setInputData] = useState('')
    const handleChange = e => {
        setInputData(e.target.value) //input데이터 state로 관리
    }

    //3. 데이터 추가시 input의 값으로 1번 데이터 수정
    const handleClick = e => {
        let obj = {id: list[list.length-1].id + 1 , topic: inputData} //추가할데이터(마지막요소의 id+1, 인풋데이터)
        let newList = list.concat(obj) //state와 추가할 데이터 합치기(배열합치기)
        setList(newList); //state업데이트
        setInputData(''); //input값 비우기
    }

    return (
        <div>
            <hr/>
            <input type="text" onChange={handleChange} value={inputData}/>
            <button onClick={handleClick}>추가하기</button>
            <ul>
                {newData}
            </ul>
        </div>
    )

}

export default IterationComponent2;

 

*수업 코드

import { useState } from "react";


const IterationComponent2 = () => {

        //1. 반복할 데이터 (state로 관리)
    const arr = [
        {id: 1, topic: 'hello'},
        {id: 2, topic: 'bye'},
        {id: 3, topic: 'see you'},
    ];
    const [list, setList] = useState(arr);

    //2. map함수를 이용해서 li태그로 생성
    const newList = list.map((item, index) => 
        <li key={item.id} onDoubleClick = {() => handleRemove(item.id)}>
            {item.topic}
        </li>
    )

    //3. 인풋데이터 관리
    const [data, setData] = useState('');
    const handleChange = (e) => {
        setData(e.target.value);
    }

    //4. 추가하기 버튼 클릭시 input의 값을 list 마지막에 추가
    const handleClick = () => {
        let obj = {id : list[list.length-1].id + 1 , topic : data}
        // list.push(obj); // state를 직접 변경 x

        //배열.concat(배열); 해주면 기존 배열에 새 배열을 추가해줌.
        let newArr = list.concat(obj); //리스트에 obj에 합쳐진 새로운 리스트 반환

        setList(newArr); //state변경
        setData(''); //input값 초기화
    }

    //5. 삭제기능
    //화살표 함수는 익명함수기 때문에 호이스팅(함수연결) 불가
    //이벤트 안에서 함수를 호출로 연결하는 방법
    //onClick={ () => 함수()}
    const handleRemove = (a) => { 
        // console.log(a); //키
        //filter - 콜백의 리턴이 true인 값을 가지고 새로운 배열생성
        // const ex =[1,2,3,4,5].filter((item) => item != 3)
        // console.log(ex);

        const newList = list.filter(item => item.id !== a);
        setList(newList);

    }



    return(
        <>
            <h3>목록 추가하기</h3>
            <input type="text" onChange={handleChange} value={data}/>
            <button type="button" onClick={handleClick}>추가하기</button>
            <ul>
                {newList}
            </ul>
        </>
    )

}

export default  IterationComponent2;

 

#리액트에서 이미지를 가져오는 방법

이미지를 가져오는 방법
1. 외부 서버에서 경로를 참조받음 (가장 일반적인 방법)

2.src폴더 밑에 img 파일 참조가능 (선호 x)
import img1 from '../img/img1.png';

3. public폴더 밑에 넣는 경우 이미지를 바로 참조 가능 (선생님이 추천하시는 방법)

 

#실습

*IterationComponentQ.js

/*
이미지를 가져오는 방법
1. 외부 서버에서 경로를 참조받음 (가장 일반적인 방법)

2.src폴더 밑에 img 파일 참조가능 (선호 x)
import img1 from '../img/img1.png';

3. public폴더 밑에 넣는 경우 이미지를 바로 참조 가능 (선생님이 추천하시는 방법)
*/

import { useState } from "react";

const IterationComponentQ = () => {

    const arr = [
        { src: '/img/img1.png', title: '아이폰10', price: 1000 },
        { src: '/img/img2.png', title: '아이폰11', price: 2000 },
        { src: '/img/img3.png', title: '아이폰12', price: 3000 },
        { src: '/img/img4.png', title: '아이폰13', price: 4000 },
    ]

    //1. state로 arr 관리
    const [imgs, setImgs] = useState(arr);

    //3. 클릭시에 화면에 그려질 내용을 state로 관리
    const [content, setContent] = useState({ src:'/img/img1.png' });
    const handleClick = (e) => {
        setContent({ src: e.target.src });
    }

    //2. 반복처리
    const itemList = imgs.map((item, index) =>
        <div key={item.src}>
            <img src={item.src} alt={item.title} width="100" onClick={handleClick} />
            <p>{item.title}</p>
            <p>{item.price}</p>
        </div>
    )



    return (
        <>
            <h3>이미지 데이터 반복하기</h3>
            <div>
                <img src={content.src} alt="이미지" width="200" />
            </div>
            {/* 
            <img src="https://raw.githubusercontent.com/yopy0817/data_example/master/img/img1.png" alt="제목" width="100"/>
            <img src={img1} alt="제목" width="100"/>
            <img src="/img/img1.png" alt="제목" width="100" />
             */}

            <div style={{ display: "flex", justifyContent: "space-around" }}>
                {/* 반복할 요소의 모형 */}
                {/* <div>
                    <img src="/img/img1.png" alt="제목" width="100" />
                    <p>제목</p>
                    <p>가격</p>
                </div> */}
                {itemList}
            </div>
        </>
    )

}

export default IterationComponentQ;

 

* IterationComponentQ2.js

import { useState } from "react";

const IterationComponentQ2 = () => {

    //1 - select태그는 컴포넌트반복으로 option태그를 생성합니다.
    const select = ['HTML', 'Javascript', 'CSS', 'Java', 'Oracle', 'Mysql']
    const options = select.map((item, index) => {
        return <option key={index}>{item}</option>
    })

    //2 - data는 state로 관리하고 화면에 li태그로 반복을 합니다.
    const data = [
        {id: 1, type: 'Java', teacher: '이순신'},
        {id: 2, type: 'Java', teacher: '홍길자'},
        {id: 3, type: 'Javascript', teacher: '홍길동'},
        {id: 4, type: 'Oracle', teacher: '이순신'},
        {id: 5, type: 'Mysql', teacher: '이순신'},
        {id: 6, type: 'CSS', teacher: '박찬호'},
        {id: 7, type: 'HTML', teacher: 'coding404'},
    ];

    const [datas, setDatas] = useState(data);
    const dataList = datas.map((item) => 
        <li key={item.id}>{item.type} - {item.teacher}</li>
        
    )

    //3. 셀렉트박스가 체인지되면, 이벤트객체를 활용해서 선택된 값만 필터링해서 보여주면 됩니다.

    function handleChange(e){
        let newList = data.filter((item) => 
            item.type === e.target.value
        )
        // console.log(newList);
        setDatas(newList);
                
    };

    //4 - 숙제: 검색 기능 만들기
    
    const [search, setSearch] = useState(''); 

    const handleChange2 = (e) => {
        setSearch(e.target.value);
    }

    const handleClick = () => {
        
        // console.log(data[0].type.toLowerCase().includes(search.toLowerCase()));
        const search_result = data.filter((item)=> {
            return item.type.toLowerCase().includes(search.toLowerCase()) || 
                   item.teacher.includes(search);
        })
        // console.log(search_result);
        setDatas(search_result);
        setSearch('');
    }

    const handleKeyDown = (e) => {
        // console.log(e.keyCode); // keyCode 가 13임을 확인
        if(e.keyCode === 13) handleClick();
    }

    return (
        <>
            <h3>컴포넌트 반복 실습</h3>
            <h3>검색기능 - 대소문자를 구분하지 않고 teacher, type에 포함된 데이터만 필터링</h3>
            <div>Search: <input type="text" onChange={handleChange2} onKeyDown={handleKeyDown} value={search}/><button type="button" onClick={handleClick}>검색</button></div>

            <select onChange={handleChange}>
                {options}
            </select>           
            <ul>
                {dataList}
            </ul> 
        </>
    )

}

export default IterationComponentQ2;

 

<기억할 점>

- 목록요소를 반복처리할 때는 map 함수를 이용한다는 것.

- filter함수를 이용한다는 것.

- 반복되는 태그에 key값을 꼭 주어야 한다는 것.

'React.js' 카테고리의 다른 글

23-01-18) 7.React에 css적용하기  (0) 2023.01.18
6. 리액트 기본훅  (0) 2023.01.17
23-01-16 4. 리액트 이벤트 핸들링  (0) 2023.01.16
23-01-16 3. state (중요) ★★★  (0) 2023.01.16
2. 리액트의 Components와 props  (0) 2023.01.13
댓글