WEB 개발 공부

Chapter 7. 데이터처리 (List and Keys, Forms)

개발 편지 2024. 4. 9. 15:57

📝 학습 목표

  1. List와 Form을 사용해서 데이터를 처리하는 방법을 알 수 있다.
  2. List와 Form을 사용할 때 주의할 점을 알 수 있다.

 


L i s t   a n d   K e y s

🌸JavaScript에서 여러 개의 컴포넌트 혹은 리스트를 사용하는 방법에 대해 설명해주세요.

이런 경우 JavaScript에서는 보통 map() 함수를 이용합니다.

map() 함수는 배열을 처리해서 새로운 배열로 반환하기 위한 함수입니다.

이런 특징 덕분에, 여러 개의 컴포넌트나 리스트를 사용할 때 자주 쓰이게 됩니다. 사용하는 방법은 다음과 같습니다.

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled); // [2, 4, 6, 8, 10]

 

여러 개의 컴포넌트를 사용할 때도 리스트를 처리할 때와 비슷합니다.

엘리먼트 모음을 만들고 중괄호를 사용해서 JSX에 포함시킵니다. 그런 다음, map() 함수를 사용해 numbers 배열을 반복 실행합니다. 각 항목에 대해 <li> 엘리먼트를 반환하고 배열의 결과를 listItems에 저장합니다.

그러면 <ul> 엘리먼트 안에 전체 listItems 배열을 포함할 수 있습니다.

 

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];
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<NumberList numbers={numbers} />);

 

🌸 map()함수를 사용할 때 key를 사용해야 하는 이유는 무엇인가요?

 

 

map() 함수가 key를 통해 요소를 식별하기 때문입니다.

key는 React가 어떤 항목을 변경, 추가 또는 삭제할지 식별하는 것을 돕습니다.

key는 엘리먼트에 안정적인 고유성을 부여하기 위해 배열 내부의 엘리먼트에 지정해야 합니다.

key를 선택할 때는 리스트의 다른 항목들 사이에서 해당 항목을 고유하게 식별할 수 있는 문자열을 사용하는 것입니다.

대부분의 경우엔 ID를 key로 사용합니다.

 

🌸 key의 올바른 사용법에 대해 조사하고, 설명해주세요.

key로 컴포넌트를 추출할 때, key는 주변 배열의 context에서만 의미가 있습니다.

예를들어 ListItem 컴포넌트를 추출한 경우 ListItem 안에 있는 <li> 엘리먼트가 아니라 배열의 <ListItem /> 엘리먼트가 key를 가져와야 합니다.

 

 

# 잘못된 예

function ListItem(props) {
  // 여기에는 key를 지정할 필요가 없습니다.
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 배열 안에 key를 지정해야 합니다.
    <ListItem key={number.toString()} value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

 

# 올바른 예

function ListItem(props) {
  // 여기에는 key를 지정할 필요가 없습니다.
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // 배열 안에 key를 지정해야 합니다.
    <ListItem key={number.toString()} value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}
```

 

key는 형제 사이에서만 고유한 값이어야 합니다.

key는 배열 안에서 형제 사이에서 고유해야 하고 전체 범위에서 고유할 필요는 없습니다.

두 개의 다른 배열을 만들 때 동일한 Key를 사용할 수 있습니다.

 

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.'}
];

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Blog posts={posts} />);

 


F o r m

 

🌸 리액트에서 폼을 사용하는 이유는 무엇인가요?

HTML 폼 엘리먼트는 폼 엘리먼트 자체가 내부 상태를 가지기 때문에, React의 다른 DOM 엘리먼트와 다르게 동작합니다. 예를 들어, 순수한 HTML에서 이 폼은 name을 입력받습니다.

<form>
  <label>
    Name:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="Submit" />
</form>

 

이 폼은 사용자가 폼을 제출하면 새로운 페이지로 이동하는 기본 HTML 폼 동작을 수행합니다.

React에서 동일한 동작을 원한다면 그대로 사용하면 됩니다. 그러나 대부분의 경우, JavaScript 함수로 폼의 제출을 처리하고 사용자가 폼에 입력한 데이터에 접근하도록 하는 것이 편리합니다.

이를 위한 표준 방식은 “제어 컴포넌트 (controlled components)“라고 불리는 기술을 이용하는 것입니다.

 

🌸 제어 컴포넌트란 무엇인가요?

HTML에서 <input>, <textarea>, <select>와 같은 폼 엘리먼트는 일반적으로 사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트합니다.

React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다.

우리는 React state를 “신뢰 가능한 단일 출처 (single source of truth)“로 만들어 두 요소를 결합할 수 있습니다.

그러면 폼을 렌더링하는 React 컴포넌트는 폼에 발생하는 사용자 입력값을 제어합니다.

이러한 방식으로 React에 의해 값이 제어되는 입력 폼 엘리먼트를 “제어 컴포넌트 (controlled component)“라고 합니다.

예를 들어, 이전 예시가 전송될 때 이름을 기록하길 원한다면 폼을 제어 컴포넌트 (controlled component)로 작성할 수 있습니다.

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

 

value 어트리뷰트는 폼 엘리먼트에 설정되므로 표시되는 값은 항상 this.state.value가 되고 React state는 신뢰 가능한 단일 출처 (single source of truth)가 됩니다.

React state를 업데이트하기 위해 모든 키 입력에서 handleChange가 동작하기 때문에 사용자가 입력할 때 보여지는 값이 업데이트됩니다.

제어 컴포넌트로 사용하면, input의 값은 항상 React state에 의해 결정됩니다.

코드를 조금 더 작성해야 한다는 의미이지만, 다른 UI 엘리먼트에 input의 값을 전달하거나 다른 이벤트 핸들러에서 값을 재설정할 수 있습니다.

🌸 textarea 태그, select 태그의 차이점을 비교하고 각 태그가 하는 역할을 작성해주세요

  • textarea태그  →  HTML에서 <textarea> 엘리먼트는 텍스트를 자식으로 정의합니다.
  • select태그     →  HTML에서 <select>는 드롭 다운 목록을 만듭니다. multiple 옵션을 허용한다면 value attribute에 배열을 전달할 수 있습니다.

 

🌸 폼 태그로 다중입력을 제어하고자 하였을 때 이를 하나로 다루는 방법은 무엇인가요?

여러 input 엘리먼트를 제어해야할 때, 각 엘리먼트에 name 어트리뷰트를 추가하고 event.target.name 값을 통해 핸들러가 어떤 작업을 할 지 선택할 수 있게 해줍니다.

class Reservation extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isGoing: true,
      numberOfGuests: 2
    };

    this.handleInputChange = this.handleInputChange.bind(this);
  }

  handleInputChange(event) {
    const target = event.target;
    const value = target.type === 'checkbox' ? target.checked : target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  render() {
    return (
      <form>
        <label>
          Is going:
          <input
            name="isGoing"
            type="checkbox"
            checked={this.state.isGoing}
            onChange={this.handleInputChange} />
        </label>
        <br />
        <label>
          Number of guests:
          <input
            name="numberOfGuests"
            type="number"
            value={this.state.numberOfGuests}
            onChange={this.handleInputChange} />
        </label>
      </form>
    );
  }
}

 

주어진 input 태그의 name에 일치하는 state를 업데이트하기 위해 ES6의 computed property name 구문을 사용하고 있습니다.

this.setState({
  [name]: value
});

 

또한, setState()는 자동적으로 현재 state에 일부 state를 병합하기 때문에 바뀐 부분에 대해서만 호출하면 됩니다.

 


 

 

자바스크립트 map() 함수 – 개념 정리 및 사용 예제 - 코딩에브리바디

map() 함수는 배열을 순회해서 콜백 함수를 사용하여 원하는 조건에 따라 처리한 새로운 배열을 반환하기 위한 함수입니다. 이 함수는 배열 내 각 요소를 변환하는데 사용되며, 변환된 결과를 모

codingeverybody.kr