Techniques for dealing with REACT_Component Repetition

the Other Object·2023년 3월 19일
0

14. map()

* arr.map(callback, [thisArg])
1. callback : 새로운 배열의 요소를 생성하는 함수
	파라미터1) currentValue : 현재 처리하고 있는 요소
    파라미터2) index : 현재 처리하고 있는 요소의 index값
    파라미터3) array : 현재 처리하고 있는 원본 배열
2. thisArg(선택항목) : callback()함수 내부에서 사용할 this 레퍼런스

const numbers = [1,2,3,4,5]
const processed = number.map( const num = () => {
  return num * num;
});
console.log(processed);

//결과 | [1,4,9,16,25]

* 동일
const numbers = [1,2,3,4,5]
const result = numbers.map(num => num*num);
console.log(result);
  • 데이터 배열을 컴포넌트 배열로 변환하기
const InterationSample = () => {
  const names = [1,2,3,4];
  const nameList = names.map(name => <li> {name} </li>);
                             
  return (
    <ul> {nameList} </ul>
  )
};

export default InterationSample;

15. key

  • 리액트에서 key는, 컴포넌트 배열을 렌더링 했을 때 어떤 원소에 변동이 있었는지 알아내기 위해 사용한다.

  • 예를 들어, 유동적인 데이터를 다룰때는 원소를 새로 생성, 제거, 수정 할 수가 있다.

  • key가 없을 때는 Virtual DOM을 비교하는 과정에서 리스트를 순차적으로 비교하면서 변화를 감지

  • 하지만, key가 있다면 이 값을 사용하여 어떤 변화가 일어났는지 더욱 빠르게 알아낼 수 있다.

  • key값을 설정할 때는 map()함수의 인자로 전달되는 함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 된다.

  • key값은 언제나 유일해야한다. 데이터가 가진 고유값을 key값으로 설정해야한다.

const articleList = articles.map(article => (
  <Article
  	title={article.title}
    writer={article.writer}
	key={article.id}
  />
));

* 고유번호가 없을 떄는, map()함수에 전달되는 콜백함수의 인수인 index값을 사용하면 된다.


//IterationSample.js

const IterationSample = () => {
  const names = [1,2,3,4];
  const nameList = names.map((name, index) => <li key={index}> {name} </li>);

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

* 고유한 값이 없을 때만 index 값을 key로 사용해야 한다.
* index를 key로 사용하면 배열이 변경될 때 효율적으로 리렌더링이 안된다.

16. 동적인 배열을 렌더링, index 아닌 고유값 만들기

  1. 초기상태 설정하기
    • useState
    • 상태설정
      (1) 데이터배열
      (2) 텍스트를 입력할 수 있는 input의 상태
      (3) 데이터 배열에서 새로운 항목을 추가할 때 사용할 고유 id를 위한 상태
import React, {useState} from 'react';

const IterationSample = () => {
  
  const [inputText, setInputText] = useState('');
  const [nextId, setNextId] = useState(5)
  const [names, setNames] = useState([
    {
      id: 1,
      text: 'aa'
    },
    {
      id: 2,
      text: 'bb'
    },
    {
      id: 3,
      text: 'cc'
    },
    {
      id: 4,
      text: 'dd'
    }
  ]);
  //map()함수를 사용할 때 key값을 index 대신 name.id값으로 지정해주었다.
  const namesList = names.map(
    name => 
    <li 
      key={name.id}
    >
       {name.text} 
	</li>
  );

  const onChange = (e) => {
    setInputText(e.target.value);
  }
  
  const onClick = () => {
    // push() : 기존배열자체를 변경해주고
    // concat() : 새로운배열을 만들어준다.
    const nextNames = names.concat({
      id: nextId,  //nextId값을 id로 설정
      text: inputText
    });
    setNextId(nextId + 1); //nextId값에 1씩 더해줌
    setNames(nextNames);  //names값을 업데이트
    setInputText('')   //inputText를 비운다.
  }

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

export default IterationSample;
  • 리액트에서 상태를 업데이트할 떄는 기존 상태를 그대로 두면서 새로운 값을 상태로 설정해야한다.
  • 이를 '불변성유지'라고 한다 => 리액트 컴포넌트의 성능 최적화

17. 데이터제거기능

  • 각 항목을 더블클릭 했을 때 해당 항목이 화면에서 사라지는 기능
  • 불변성을 유지하면서 업데이트 해줘야한다.
  • 불변성을 유지하면서 배열의 특정 항목을 지울 때 : 배열의 내장함수 filter를 사용한다.
  • filter함수를 사용하면, 배열에서 특정 조건을 만족하는 원소들만 쉽게 분류할 수 있다.
const numbers = [1,2,3,4,5,6];
const biggerThanThree = numbers.filter(number => number>3);

//결과 : [4,5,6]
  • filter()함수의 인자에 분류하고 싶은 조건을 반환하는 함수를 넣어주면 쉽게 분류할 수 있다.
  • 이 filter()함수를 응용하여 : 특정배열에서 특정원소만 제외시킬수도 있다.
// numbers 배열에서 3만 없애보자

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

//결과 | [1,2,4,5,6]
//IterationSample 컴포넌트의 항목제거기능 구현하기_ onDoubleClick, onRemove

import React, {useState} from 'react';


const IterationSample = () => {
  
  const [inputText, setInputText] = useState('');
  const [nextId, setNextId] = useState(5)
  const [names, setNames] = useState([
    {
      id: 1,
      text: 'aa'
    },
    {
      id: 2,
      text: 'bb'
    },
    {
      id: 3,
      text: 'cc'
    },
    {
      id: 4,
      text: 'dd'
    }
  ]);
  
  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>
	)
  )
  */
  
  const onChange = (e) => {
    setInputText(e.target.value);
  }
  
  const onClick = () => {
    const nextNames = names.map({id: nextId, text:inputText});
    setNames(nextNames);
    setNextId(nextId + 1);
    setInputText('')
  }
  
  
  return (
    <div>
    	<input 
    		value={inputText}
			onChange={onChange}
    	/>
        <button
			onClick={onClick}
		>
              추가
		</button>
		//<ul> {namesList} </ul>
		<ul>
           names.map(name => (
              <li
              	key={name.id}
                onDoubleClick={() => onRemove(name.id)}
              >
              	{name.text}
              </li>
           ))
        </ul>
    </div>
  );
};

export default IterationSample
* target : 실제로 이벤트가 발생한 Element객체를 참조한다. 이벤트 버블링, 캡처 단계에서도 참조가 가능하다.
* defaultPrevented : preventDefault()메소드가 이벤트에서 호출되었는지 여부를 확인할 수 있다.
* toLocaleString() : 객체를 나타내는 문자열을 사용 지역의 방식으로 출력이 된다. 상속받은 모든 객체가 사용할 수는 없고
			Array.prototype.toLocaleString()
            Number.prototype.toLocaleString()
            Date.prototype.toLocaleString()
* toString() : 객체를 나타내는 문자열을 반환
* valueOf() : 객체의 Primitive원시 값을 반환
* constructor : 객체의 생성자 함수를 참조
* __proto__ : 상속된 [[Prototype]] 참조하거나 설정가능하며 일반적으로 실제 코드상에서는 잘 사용안됨
			ECMAScript에서 사용되지 않는 비표준이지만 최신 웹브라우저에서는 비공식적으로 지원 중
* ondblclick()
const CreateSchedule = () => {

  const [inputText, setInputText] = useState('')
  const [nextId, setNextId] = useState();
  const [todos, setTodos] = useState([])




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

  const onClick = () => {
    const nextTodos = todo.concat({
      id: nextId,
      inputText: setInputText
    })
    setTodos(nextTodos);
    setNextId(nextId + 1);
    setInputText('')
  }

  return (
    <div>
      <input 
        key={inputText}
        onChange={onChange}
      />
      <button
        onClick={onClick}
      > 
        등록 
      </button>
      <ul> todos.map(todo => (
          <li key={todo.nextId}>
          	{todo.inputText}
          </li>
        ))
	  </ul>
    </div>
  )
}

export default CreateSchedule;

0개의 댓글