이 기본 문서에 수록된 모든 기본 React.js 개념

React의 이유, 이유 및 방법을 배우는 소개

이 기사는 jsComplete.com/react-intro의 대화식 안내서를 수정 한 것입니다. jsComplete 버전에는 코드 예제와 컨텐츠를 탐색하는 링크가 포함되어 있습니다.
시작하기 전에이 문서는 React 작업을위한 기본으로 분류 한 개념을 다루는 초보자 용 안내서입니다. React에 대한 완전한 안내서가 아니라 완전한 소개입니다.
이 안내서의 끝에는 다음 몇 가지 수준의 리소스가 나와 있습니다. 이 안내서는 당신이 그들을 이해할 수있는 길을 열어 줄 것입니다.

React는 사용자 인터페이스를 구축하기위한 JavaScript 라이브러리로 정의됩니다. 이 정의의 두 가지 다른 부분에 대해 이야기하겠습니다.

React는 JavaScript "라이브러리"입니다. 정확히 "프레임 워크"가 아닙니다. 완벽한 솔루션은 아니며 솔루션을 구성하기 위해 React와 함께 더 많은 라이브러리를 사용해야하는 경우가 종종 있습니다. React는 솔루션의 다른 부분에 대해서는 아무 것도 가정하지 않습니다.

프레임 워크는 특히 젊은 팀과 스타트 업에게 큰 목적을 제공합니다. 프레임 워크로 작업 할 때 많은 스마트 한 디자인 결정이 이미 이루어 졌으므로 우수한 응용 프로그램 수준의 논리를 작성하는 데 집중할 수 있습니다. 그러나 프레임 워크에는 몇 가지 단점이 있습니다. 대규모 코드베이스를 작업하는 숙련 된 개발자에게는 이러한 단점이 종종 거래 차단기입니다.

일부는 주장하지만 프레임 워크는 유연하지 않습니다. 프레임 워크는 일반적으로 모든 것을 특정 방식으로 코딩하기를 원합니다. 당신이 그런 식으로 벗어나려고하면, 프레임 워크는 일반적으로 그것에 대해 싸우게됩니다. 프레임 워크는 일반적으로 크고 기능이 가득합니다. 작은 조각 만 사용해야하는 경우 어쨌든 전체를 포함해야합니다. 분명히이 점은 오늘날 바뀌고 있지만 여전히 이상적이지는 않습니다. 일부 프레임 워크는 모듈화되고 있습니다. 저는 훌륭하다고 생각하지만, 순수한 유닉스 철학의 큰 팬입니다.

한 가지 일을 잘 수행하는 프로그램을 작성하십시오. 함께 일할 프로그램을 작성하십시오.
— 더그 맥 일로이

React는 유닉스 철학을 따르고 있습니다. 하나의 일에만 집중하고 그 일을 매우 잘 수행하는 작은 라이브러리이기 때문입니다. 그 "한 가지"는 React 정의의 두 번째 부분 인 사용자 인터페이스 구축입니다.

사용자 인터페이스 (UI)는 사용자가 기계와 상호 작용하도록하기 위해 사용자 앞에 놓는 것입니다. 전자 레인지의 간단한 버튼부터 우주 왕복선의 대시 보드에 이르기까지 UI가 어디에나 있습니다. 인터페이스하려는 장치가 JavaScript를 이해할 수있는 경우 React를 사용하여 UI를 설명 할 수 있습니다. 웹 브라우저는 JavaScript를 이해하므로 React를 사용하여 웹 UI를 설명 할 수 있습니다.

여기서 설명하는 단어는 기본적으로 React에서 수행하는 작업이므로 사용하고 싶습니다. 우리는 단지 우리가 원하는 것을 말해줍니다! React는 웹 브라우저를 통해 실제 UI를 구축 할 것입니다. React 또는 유사한 라이브러리가 없으면 기본 웹 API 및 JavaScript를 사용하여 UI를 수동으로 빌드해야하므로 쉽지 않습니다.

“반응은 선언적”이라는 문장을들을 때 이것이 정확히 의미하는 바입니다. 우리는 React로 UI를 설명하고 원하는 것을 알려줍니다 (어떻게하는지). React는“어떻게”를 처리하고 선언적 설명 (React 언어로 작성)을 브라우저의 실제 UI로 변환합니다. React는이 간단한 선언적 힘을 HTML 자체와 공유하지만 React를 사용하면 정적 데이터뿐만 아니라 동적 데이터를 나타내는 HTML UI에 대해서도 선언적입니다.

React가 출시되었을 때 실제 DOM을 조정하는 데 사용할 수있는 가상 DOM에 대한 현명한 아이디어를 도입했기 때문에 성능에 대한 많은 소문이있었습니다 (다음 섹션에서 이에 대해 이야기하겠습니다).

DOM은 "문서 객체 모델"입니다. HTML (및 XML) 문서를 트리 구조로 취급하는 브라우저의 프로그래밍 인터페이스입니다. DOM API를 사용하여 문서 구조, 스타일 및 컨텐츠를 변경할 수 있습니다.

React의 성능은 여전히 ​​오늘날 인기가 높은 가장 중요한 이유 중 하나이지만, React의 성능은 "최고의"것으로 분류되지 않습니다. React는 개발자와 브라우저 사이에 공통 언어를 생성하여 개발자가 DOM 요소에 대한 조치 대신 UI를 선언적으로 설명하고 상태에 대한 조치를 관리 할 수있게했기 때문에 게임 체인저라고 생각합니다. 단순히 사용자 인터페이스의 언어가 "성과"입니다. 인터페이스에서 동작을 설명하는 단계를 수행하는 대신 개발자는 인터페이스를 "최종"상태 (함수와 같은)로 설명합니다. 액션이 해당 상태에 도달하면 React는이를 기반으로 DOM의 UI 업데이트를 처리합니다 (다음에 볼 수 있듯이 효율적으로 수행).

누군가 React가 왜 배울 가치가 있는지 한 가지 이유를 말해달라고 요청한 경우, 결과 기반 UI 언어가 바로 그 것입니다. 나는이 언어를“React language”라고 부릅니다.

반응 언어

다음과 같은 TODO 목록이 있다고 가정하십시오.

const todos : [
  {본문 : 'Learn React Fundamentals', 완료 : true},
  {본문 : 'TODOs 앱 빌드'완료 : false},
  {본문 : '게임 만들기', 완료 : 거짓},
];

이 할 일 모음은 UI의 시작 상태입니다. UI를 표시하고 관리하려면 UI를 구축해야합니다. UI에는 새 TODO를 추가하는 양식, TODO를 완료로 표시하는 방법 및 완료된 모든 TODO를 제거하는 방법이 있습니다.

이러한 각 작업에는 앱이 DOM 작업을 수행하여 DOM 노드를 생성, 삽입, 업데이트 또는 삭제해야합니다. React를 사용하면 이러한 모든 DOM 작업에 대해 걱정할 필요가 없습니다. 언제 발생해야하는지 또는 효율적으로 수행하는 방법에 대해 걱정하지 않아도됩니다. todos 배열을 앱의 "상태"에 놓은 다음 React 언어를 사용하여 React를 "명령"하여 UI에 특정 방식으로 해당 상태를 표시하십시오.

TODO 목록
      {todos.map (todo =>     
  • {todo.body}   )}
// 다른 폼 요소들 ...

구문에 대해 걱정하지 않아도 진행 상황이 궁금하다면 JavaScript 객체 배열을 React 요소 배열에 매핑하기 만하면됩니다. 더 빨리.

그런 다음 해당 todos 배열에서 데이터 조작을 수행하는 데 집중할 수 있습니다! 해당 배열의 항목을 추가, 제거 및 업데이트하면 React는 브라우저에서 렌더링 된 UI에이 객체에 대한 변경 사항을 반영합니다.

최종 상태를 기반으로 UI를 모델링하는이 정신 모델은 특히 뷰에 많은 데이터 전환이있을 때 이해하고 작업하기가 더 쉽습니다. 예를 들어, 얼마나 많은 친구가 온라인에 있는지 알려주는 견해를 고려하십시오. 이 뷰의 '상태'는 현재 온라인 상태 인 친구 수의 단일 숫자 일뿐입니다. 얼마 전 세 명의 친구가 온라인에 접속 한 후 그 중 한 명은 연결을 끊은 다음 두 명은 더 합류했다고 신경 쓰지 않습니다. 현재이 순간에 네 명의 친구가 온라인 상태임을 알고 있습니다.

반응의 나무 화해

React 이전에는 DOM API로 알려진 브라우저 API로 작업해야 할 때 DOM 트리를 최대한 많이 탐색하지 않았으며 그 이유가 있습니다. DOM에서의 모든 작업은 입력, 스크롤, 크기 조정 등과 같은 사용자 이벤트에 대한 반응을 포함하여 브라우저에서 발생하는 다른 모든 작업을 담당하는 동일한 단일 스레드에서 수행됩니다.

DOM에서의 값 비싼 작업은 사용자에게 느리고 고르지 않은 경험을 의미합니다. 애플리케이션이 절대 최소 작업을 수행하고 가능한 경우 배치하는 것이 매우 중요합니다. React는 우리가 정확히 그렇게 할 수 있도록 독창적 인 개념을 고안했습니다!

브라우저에서 요소 트리를 렌더링하도록 React에 지시하면 먼저 해당 트리의 가상 표현을 생성하고 나중에 메모리에 유지합니다. 그런 다음 브라우저에 트리를 표시하는 DOM 작업을 계속 진행합니다.

이전에 렌더링 한 요소 트리를 업데이트하도록 React에 지시하면 업데이트 된 트리의 새로운 가상 표현이 생성됩니다. 이제 React에는 메모리에 2 가지 버전의 트리가 있습니다!

브라우저에서 업데이트 된 트리를 렌더링하기 위해 React는 이미 렌더링 된 것을 버리지 않습니다. 대신 메모리에있는 2 개의 가상 버전의 트리를 비교하고 차이점을 계산하고 기본 트리의 어떤 하위 트리를 업데이트해야하는지 확인한 다음 브라우저에서 이러한 하위 트리 만 업데이트합니다.

이 프로세스는 트리 조정 알고리즘으로 알려져 있으며 React를 브라우저의 DOM 트리로 작업하는 데 매우 효율적인 방법입니다. 우리는 곧 그 예를 보게 될 것입니다.

선언적 결과 기반 언어 및 효율적인 트리 조정 외에도 React가 큰 인기를 얻은 이유는 다음과 같습니다.

  • DOM API로 작업하는 것은 어렵습니다. React는 개발자에게 실제 브라우저보다 친숙한 "가상"브라우저로 작업 할 수있는 기능을 제공합니다. React는 기본적으로 귀하를 대신하여 DOM과 통신하는 에이전트와 같은 역할을합니다.
  • 반응에는 종종 "Just JavaScript"레이블이 붙어 있습니다. 이것은 배우는 API가 매우 작다는 것을 의미하며 그 후에 JavaScript 기술이 더 나은 React 개발자가됩니다. 이는 API가 더 큰 라이브러리보다 이점입니다. 또한 React API는 대부분 함수이며 필요한 경우 클래스입니다. UI 뷰가 데이터의 기능이라고 들리면 React에서 말 그대로 그럴 것입니다.
  • Learning React는 iOS 및 Android 모바일 애플리케이션에도 큰 도움이됩니다. React Native를 사용하면 React 기술을 사용하여 기본 모바일 애플리케이션을 구축 할 수 있습니다. 웹, iOS 및 Android 애플리케이션간에 논리를 공유 할 수도 있습니다.
  • Facebook의 React 팀은 facebook.com에서 React에 도입 된 모든 개선 사항 및 새로운 기능을 테스트하여 커뮤니티 간의 라이브러리에 대한 신뢰를 높입니다. Facebook에서 철저한 생산 테스트를 거친 후에 만 ​​릴리스되기 때문에 React 릴리스에서 크고 심각한 버그는 거의 없습니다. React는 또한 Netflix, Twitter, Airbnb 등과 같이 많이 사용되는 다른 웹 애플리케이션을 지원합니다.

첫 반응 예

트리 조정 프로세스의 실질적인 이점과 그 큰 차이를 확인하려면 해당 개념에만 초점을 둔 간단한 예를 살펴 보겠습니다. 기본 웹 API를 사용한 후 React API (및 해당 조정 작업)를 사용하여 HTML 요소 트리를 두 번 생성하고 업데이트하겠습니다. 이 예제를 단순하게 유지하기 위해 컴포넌트 또는 JSX (React에서 널리 사용되는 JavaScript 확장)를 사용하지 않습니다. 또한 JavaScript 간격 타이머 내에서 업데이트 작업을 수행합니다. 이것이 우리가 React 애플리케이션을 작성하는 방법이 아니라 한 번에 하나의 개념에 초점을 맞추겠습니다.

이 jsComplete 놀이터 세션 (jsdrops.com/react-dom1)으로 시작하십시오.

이 세션에서 간단한 HTML 요소는 두 가지 방법을 사용하여 디스플레이에 렌더링됩니다.

방법 # 1 : 웹 DOM API를 직접 사용

document.getElementById ( 'mountNode'). innerHTML =`
  
    안녕하세요 HTML    `;

방법 # 2 : React의 API 사용

ReactDOM.render (
  React.createElement (
    'div',
    없는,
    '안녕하세요 반응',
  ),
  document.getElementById ( 'mountNode2'),
);

ReactDOM.render 메소드 및 React.createElement 메소드는 React 애플리케이션의 핵심 API 메소드입니다. 사실,이 두 가지 방법을 모두 사용하지 않으면 React 웹 애플리케이션이 존재할 수 없습니다. 간단히 설명하겠습니다 :

ReactDOM.render

이것은 기본적으로 브라우저의 DOM에 React 애플리케이션의 진입 점입니다. 2 개의 인수가 있습니다.

  1. 첫 번째 인수는 브라우저에 렌더링하는 것입니다. 이것은 항상“반응 요소”입니다.
  2. 두 번째 인수는 브라우저에서 해당 React 요소를 렌더링하는 위치입니다. 정적으로 렌더링 된 HTML에 존재하는 유효한 DOM 노드 여야합니다. 위의 예제는 놀이터의 표시 영역에 존재하는 특수한 mountNode2 요소를 사용합니다 (첫 번째 mountNode는 기본 버전에 사용됨).

정확히 React 요소는 무엇입니까? DOM 요소를 설명하는 가상 요소입니다. React.createElement API 메소드가 리턴하는 것입니다.

React.createElement

React에서 문자열을 사용하여 DOM 요소 (위의 기본 DOM 예제에서와 같이)를 나타내는 대신 React.createElement 메소드에 대한 호출을 사용하여 객체로 DOM 요소를 나타냅니다. 이러한 객체를 반응 요소라고합니다.

React.createElement 함수에는 많은 인수가 있습니다.

  1. 첫 번째 인수는 DOM 요소가 나타내는 HTML "태그"이며이 예에서는 div입니다.
  2. 두 번째 인수는 DOM 요소에 원하는 모든 속성 (예 : id, href, title 등)에 대한 것입니다. 우리가 사용하는 간단한 div에는 속성이 없으므로 null을 사용했습니다.
  3. 세 번째 인수는 DOM 요소의 내용입니다. 거기에 "Hello React"문자열을 넣었습니다. 선택적 세 번째 인수와 렌더링 된 요소의 하위 목록을 구성한 후의 모든 선택적 인수입니다. 요소는 0 개 이상의 자식을 가질 수 있습니다.
React.createElement를 사용하여 React 컴포넌트에서 요소를 작성할 수도 있습니다.

반응 요소는 메모리에 생성됩니다. 실제로 React 요소를 DOM에 표시하기 위해 ReactDOM.render 메소드를 사용하여 React 요소의 상태를 브라우저의 실제 DOM 트리에 반영하는 가장 최적의 방법을 알아냅니다.

이 코드 세션에서 두 가지 방법을 실행하면 "Hello HTML"상자와 "Hello React"상자가 나타납니다.

중첩 반응 요소

우리는 두 개의 노드가 있습니다. 하나는 DOM API로 직접 제어되고 다른 하나는 React API로 제어됩니다 (다시 DOM API를 사용함). 브라우저에서이 두 노드를 구축하는 방법 간의 유일한 주요 차이점은 HTML 버전에서는 문자열을 사용하여 DOM 트리를 나타내는 반면 React 버전에서는 순수한 JavaScript 호출을 사용하고 DOM 트리를 객체로 표현했다는 것입니다 문자열 대신.

HTML UI가 아무리 복잡 해지더라도 React를 사용할 때 모든 HTML 요소는 React 요소로 표시됩니다.

이 간단한 UI에 HTML 요소를 더 추가하겠습니다. 사용자의 입력을 읽을 수있는 텍스트 상자를 추가하겠습니다. HTML 버전의 경우 템플릿 내에 직접 새 요소의 태그를 삽입하면됩니다.

document.getElementById ( 'mountNode'). innerHTML =`
  
    안녕하세요 HTML     <입력 />    `;

React와 동일한 작업을 수행하려면 위의 React.createElement에 대한 세 번째 인수 뒤에 추가 인수를 추가 할 수 있습니다. 지금까지 네이티브 DOM 예제의 내용과 일치시키기 위해 입력 요소를 렌더링하는 또 다른 React.createElement 호출 인 네 번째 인수를 추가 할 수 있습니다.

ReactDOM.render (
  React.createElement (
    "div",
    없는,
    "안녕하세요",
    React.createElement ( "input")
  ),
  document.getElementById ( 'mountNode2'),
);

두 버전 모두에서 현재 시간을 렌더링 해 보겠습니다. 사전 요소 (놀이터에 고정 폭 글꼴)를 넣습니다. new Date (). toLocaleTimeString ()을 사용하여 간단한 시간 문자열을 표시 할 수 있습니다. 기본 DOM 버전에 필요한 작업은 다음과 같습니다.

document.getElementById ( 'mountNode1'). innerHTML =`
  
    안녕하세요 HTML     <입력 />     
 $ {new Date (). toLocaleTimeString ()} 
  
`;

React에서 동일한 작업을 수행하기 위해 최상위 div 요소에 다섯 번째 인수를 추가합니다. 이 새로운 다섯 번째 인수는 또 다른 React.createElement 호출이며, 이번에는 컨텐츠에 대해 새로운 Date (). toLocaleTimeString () 문자열과 함께 프리 태그를 사용합니다.

ReactDOM.render (
  React.createElement (
    'div',
    없는,
    '안녕하세요 반응',
    React.createElement ( 'input'),
    React.createElement (
      '사전',
      없는,
      새로운 Date (). toLocaleTimeString ()
    )
  ),
  document.getElementById ( 'mountNode2')
);

두 버전 모두 여전히 브라우저에서 똑같은 HTML을 렌더링합니다.

아마 지금 생각하고 있듯이 React를 사용하는 것은 간단하고 친숙한 기본 방법보다 훨씬 어렵습니다. React가 잘하는 것은 친숙한 HTML을 포기하고 HTML로 간단히 쓸 수있는 것을 작성하기 위해 새로운 API를 배워야 할 가치가있는 것은 무엇입니까?

대답은 첫 번째 HTML 뷰를 렌더링하는 것이 아닙니다. DOM에서 기존 뷰를 업데이트하기 위해해야 ​​할 일입니다.

리 액트 요소 업데이트

지금까지 가지고 있던 DOM 트리에서 업데이트 작업을하겠습니다. 단순히 시간 문자열을 매 초마다 똑같이 만들자.

setInterval Web timer API를 사용하여 브라우저에서 JavaScript 함수 호출을 쉽게 반복 할 수 있습니다. 두 버전에 대한 모든 DOM 조작을 함수에 넣고 렌더링 이름을 지정한 다음 setInterval 호출에 사용하여 매초마다 반복하도록하겠습니다.

이 예제의 전체 최종 코드는 다음과 같습니다.

// jsdrops.com/react-dom2
const render = () => {
  document.getElementById ( 'mountNode'). innerHTML =`
    
      안녕하세요 HTML       <입력 />       
 $ {new Date (). toLocaleTimeString ()} 
    
  `;
  ReactDOM.render (
    React.createElement (
      'div',
      없는,
      '안녕하세요 반응',
      React.createElement ( 'input', null),
      React.createElement (
        '사전',
        없는,
        새로운 Date (). toLocaleTimeString ()
      )
    ),
    document.getElementById ( 'mountNode2')
  );
};
setInterval (렌더링, 1000);

jsdrops.com/react-dom2에서이 코드를 실행 한 결과를 확인하고 두 버전에서 시간 문자열이 1 초마다 어떻게되는지 확인하십시오. 이제 DOM에서 UI를 업데이트하고 있습니다.

React가 잠재적으로 당신의 마음을 날려 버릴 순간입니다. 기본 DOM 버전의 텍스트 상자에 무언가를 입력하려고하면 사용할 수 없습니다. 우리는 기본적으로 모든 틱에서 전체 DOM 노드를 버리고 다시 생성하기 때문에 매우 기대됩니다. 그러나 React로 렌더링 된 텍스트 상자에 무언가를 입력하려고하면 확실히 그렇게 할 수 있습니다!

전체 React 렌더링 코드가 티킹 타이머 내에 있지만 React는 전체 DOM 트리가 아닌 사전 요소의 내용 만 변경합니다. 그렇기 때문에 텍스트 입력 상자가 재생성되지 않아 입력 할 수있었습니다.

Chrome DevTools 요소 패널에서 두 개의 DOM 노드를 검사하면 DOM을 시각적으로 업데이트하는 다양한 방법을 볼 수 있습니다. Chrome DevTools 요소 패널은 업데이트되는 모든 DOM 요소를 강조 표시합니다. 네이티브 HTML 버전이 모든 눈금으로 전체 div # mountNode 컨테이너를 재생성하는 방법을 볼 수 있지만 React는 div # mountNode2 컨테이너에서 사전 태그 만 현명하게 재생성합니다.

이것이 React의 현명한 확산 알고리즘입니다. 기본 DOM 트리에서 실제로 업데이트 해야하는 내용 만 업데이트하고 다른 모든 항목은 동일하게 유지합니다. 이 diffing 프로세스는 React의 가상 DOM 표현으로 인해 메모리에 유지되므로 가능합니다. UI보기를 몇 번이나 다시 생성해야하더라도 React는 필요한 "부분"업데이트 만 브라우저로 가져갑니다.

이 방법은 훨씬 더 효율적일뿐만 아니라 UI 업데이트에 대한 생각에서 복잡성을 제거합니다. React를 사용하면 DOM을 업데이트해야하는지 여부에 대한 모든 계산을 수행 할 수 있으므로 데이터 (상태)와 UI를 설명하는 방법에 대한 생각에 집중할 수 있습니다. 그런 다음 브라우저의 실제 UI에 이러한 업데이트를 반영하는 데 필요한 단계에 대해 걱정하지 않고 필요에 따라 데이터 상태에 대한 업데이트를 관리합니다 (React가 정확히 그렇게하고 효율적인 방식으로 수행한다는 것을 알고 있기 때문에)!

반응은 구성 요소에 관한 것입니다.

React에서 재사용 가능하고 구성 가능하며 상태 저장이 가능한 컴포넌트를 사용하여 UI를 설명합니다.

작은 구성 요소를 정의한 다음 함께 구성하여 더 큰 구성 요소를 만듭니다. 작거나 큰 모든 구성 요소는 다른 프로젝트에서도 재사용 할 수 있습니다.

컴포넌트를 간단한 함수 (모든 프로그래밍 언어)로 생각할 수 있습니다. 입력이있는 함수를 호출하고 출력을 제공합니다. 필요에 따라 기능을 재사용하고 더 작은 기능으로 더 큰 기능을 구성 할 수 있습니다.

반응 구성 요소는 정확히 동일합니다. 입력은 "props"세트이고 출력은 UI에 대한 설명입니다. 여러 UI에서 단일 구성 요소를 재사용 할 수 있으며 구성 요소에는 다른 구성 요소가 포함될 수 있습니다. React 컴포넌트의 기본 형식은 실제로 평범한 JavaScript 함수입니다.

일부 React 구성 요소는 순수하지만 구성 요소에 부작용을 일으킬 수도 있습니다. 예를 들어, 구성 요소는 브라우저에 마운트 될 때 웹 페이지의 HTML“제목”을 변경하거나 브라우저보기를 특정 위치로 스크롤 할 수 있습니다.

가장 중요한 것은 React 컴포넌트가 컴포넌트의 수명주기 동안 변경 될 수있는 데이터를 보유하기위한 개인 상태를 가질 수 있다는 것입니다. 이 비공개 상태는 컴포넌트의 출력을 유도하는 입력의 암시 적 부분이며 실제로 React에 이름을 부여합니다.

왜 React의 이름이“React”입니까?
입력의 일부인 React 컴포넌트의 상태가 변경되면이를 나타내는 UI (출력)도 변경됩니다. UI 설명의 이러한 변경 사항은 작업중인 장치에 반영되어야합니다. 브라우저에서 DOM 트리를 업데이트해야합니다. React 애플리케이션에서는 수동으로 수행하지 않습니다. React는 단순히 상태 변경에 반응하고 필요할 때 DOM을 자동으로 (그리고 효율적으로) 업데이트합니다.

함수를 사용하여 컴포넌트 생성

가장 간단한 형태의 React 컴포넌트는 일반 JavaScript 함수입니다.

// jsdrops.com/bx1
기능 버튼 (소품) {
  // 여기에 DOM / React 요소를 반환합니다. 예를 들면 다음과 같습니다.
  return 
// 브라우저에서 Button 요소를 렌더링하려면
ReactDOM.render (

위의 Button 함수의 반환 된 출력에서 ​​HTML처럼 보이는 것을 어떻게 작성했는지 주목하십시오. 이것은 HTML도 아니고 JavaScript도 아니며 React도 아닙니다. 이것은 JSX입니다. HTML과 유사한 구문으로 함수 호출을 작성할 수있는 JavaScript의 확장입니다.

계속해서 Button 함수 안에 다른 HTML 요소를 반환하고 모두 지원되는 방식을 확인하십시오 (예 : 입력 요소 또는 텍스트 영역 요소 반환).

JSX는 HTML이 아닙니다

브라우저는 JSX를 이해하지 못합니다. 일반 브라우저 콘솔에서 버튼 기능을 실행하려고하면 JSX 파트의 첫 번째 문자에 대해 불평합니다.

브라우저가 이해하는 것은 (React 라이브러리가 포함되어 있음) React.createElementAPI 호출입니다. 다음과 같이 JSX없이 동일한 버튼 예제를 작성할 수 있습니다.

// jsdrops.com/bx2
기능 버튼 (소품) {
  React.createElement (를 반환
    "단추",
    {유형 : "제출"},
    props.label
  );
}
ReactDOM.render (
  React.createElement (버튼, {레이블 : "저장"}),
  mountNode
);

JSX없이 React를 이와 같이 사용할 수 있습니다. React 라이브러리를로드 한 후 브라우저에서 직접 Button 기능을 실행할 수 있으며 정상적으로 작동합니다. 그러나 함수 호출을 처리하는 대신 HTML을보고 작업하고 싶습니다. JavaScript 만 사용하고 HTML을 사용하지 않는 웹 사이트를 마지막으로 구축 한시기는 언제입니까? 원한다면 할 수 있지만 아무도 그렇게하지 않습니다. 이것이 JSX가 존재하는 이유입니다.

JSX는 기본적으로 타협입니다. React.createElement 구문을 사용하여 React 컴포넌트를 작성하는 대신 HTML과 매우 유사한 구문을 사용한 다음 컴파일러를 사용하여 React.createElement 호출로 변환합니다.

한 형태의 구문을 다른 형태의 구문으로 변환하는 컴파일러를 "트랜스 플러"라고합니다. JSX를 번역하기 위해 Babel 또는 TypeScript와 같은 변환기를 사용할 수 있습니다. 예를 들어 jsComplete 놀이터는 TypeScript를 사용하여 JSX를 넣습니다. create-react-app를 사용하면 생성 된 앱은 내부적으로 Babel을 사용하여 JSX를 변환합니다.

babeljs.io/repl/을 사용하여 JSX 구문이 React를 위해 변환되는 것을 볼 수 있지만 JSX도 자체적으로 사용할 수 있습니다. React 전용이 아닙니다.

따라서 React 구성 요소는 React 요소 (일반적으로 JSX)를 반환하는 JavaScript 함수입니다. JSX가 사용되면

이름은 대문자로 시작해야합니다

구성 요소의 이름을 "Button"으로 지정했습니다. HTML 문자와 React 요소의 혼합을 다루기 때문에 첫 번째 문자는 대문자입니다. Babel과 같은 JSX 컴파일러는 소문자로 시작하는 모든 이름을 HTML 요소의 이름으로 간주합니다. React 요소는 변수로 전달되어야하지만 HTML 요소는 React.createElement 호출에 문자열로 전달되므로 중요합니다.

계속해서 "Button"대신 React 컴포넌트의 이름을 "button"으로 지정하고 ReactDOM이 어떻게 함수를 완전히 무시하고 빈 HTML 버튼 요소를 렌더링하는지 확인하십시오.

// jsdrops.com/bx3
// 잘못된:
기능 버튼 () {
  
내 멋진 버튼 ; };
// 다음은 HTML 버튼을 렌더링합니다.
// (그리고 팬시 버튼 기능은 무시)
ReactDOM.render (

첫 번째 주장은“소품”의 대상이다

HTML 요소에 id 또는 title과 같은 속성을 할당 할 수있는 것처럼 React 요소는 렌더링 될 때 속성 목록을받을 수도 있습니다. 위의 Button 요소 (jsdrops.com/bx2)에 레이블 속성이 수신되었습니다. React에서 React 요소가 수신 한 속성 목록을 props라고합니다. React 함수 컴포넌트는이 목록을 첫 번째 인수로받습니다. 이 목록은 속성 이름을 나타내는 키와 할당 된 값을 나타내는 값이있는 객체로 전달됩니다.

함수 구성 요소를 사용하는 경우 속성 목록을 보유한 오브젝트의 이름을 "props"로 지정할 필요는 없지만 이것이 표준 관행입니다. 아래에서 수행 할 클래스 구성 요소를 사용할 때 항상 동일한 속성 목록에 props라는 특수 인스턴스 속성이 표시됩니다.

소품을받는 것은 선택 사항입니다. 일부 구성 요소에는 소품이 없습니다. 그러나 구성 요소의 반환 값은 선택 사항이 아닙니다. React 컴포넌트는 "명시 적으로 또는 암시 적으로"정의되지 않은 "을 반환 할 수 없습니다. 값을 반환해야합니다. "null"을 반환하여 렌더러가 출력을 무시하게 할 수 있습니다.

구성 요소 소품 (또는 실제로 상태)을 사용할 때마다 객체 파괴를 사용하고 싶습니다. 예를 들어, 버튼 구성 요소 기능은 소품을 구조화하여 다음과 같이 작성할 수 있습니다.

const 버튼 = ({label}) => (
  

이 방법에는 많은 이점이 있지만 가장 중요한 방법은 구성 요소에 사용되는 소품을 육안으로 검사하여 구성 요소에 필요없는 추가 소품을받지 않도록하는 것입니다.

일반 기능 대신 화살표 기능을 어떻게 사용했는지 주목하십시오. 이것은 나에게 개인적으로 선호하는 스타일입니다. 어떤 사람들은 일반적인 함수 스타일을 선호하며 그에 아무런 문제가 없습니다. 중요한 것은 선택한 스타일과 일관성을 유지하는 것입니다. 여기서는 화살표 기능을 사용하지만이를 요구 사항으로 해석하지는 않습니다.

JSX의 표현

JSX 내에서 중괄호 쌍을 사용하여 JavaScript 표현식을 포함 할 수 있습니다.

// jsdrops.com/bx4
const RandomValue = () => (
  
    {Math.floor (Math.random () * 100)}    );
ReactDOM.render (, mountNode);

이 중괄호 안에는 표현식 만 포함될 수 있습니다. 예를 들어 정규 if 문을 포함 할 수 없지만 삼항 식은 괜찮습니다. 값을 반환하는 것은 괜찮습니다. 언제든지 코드를 함수에 넣고 무언가를 반환하고 중괄호 안에 해당 함수를 호출 할 수 있습니다. 그러나이 중괄호에 넣은 논리는 최소한으로 유지하십시오.

JavaScript 변수도 표현식이므로 구성 요소가 소품 목록을 받으면이 소품을 중괄호 안에 사용할 수 있습니다. 이것이 Button 예제에서 {label}을 사용한 방식입니다.

JavaScript 객체 리터럴도 표현식입니다. 중괄호 안에 JavaScript 객체를 사용하여 {{a : 42}}와 같이 이중 중괄호처럼 보이게합니다. 이것은 다른 구문이 아닙니다. 일반적인 JSX 중괄호 안에 정의 된 객체 리터럴 일뿐입니다.

예를 들어,이 중괄호 안에 객체 리터럴을 사용하는 사용 사례 중 하나는 CSS 스타일 객체를 React의 특수 스타일 속성으로 전달하는 것입니다.

// jsdrops.com/bx5
const ErrorDisplay = ({메시지}) => (
  
    {메시지}    );
ReactDOM.render (
  <오류 표시
    message = "이것은 당신이 찾고있는 드로이드가 아닙니다"
  />,
  mountNode
);

위의 스타일 속성은 특별한 것입니다. 객체를 값으로 사용하고 해당 객체는 마치 JavaScript DOM API (카멜 케이스 속성 이름, 문자열 값)를 통해 스타일을 설정하는 것처럼 스타일을 정의합니다. React는 이러한 스타일 객체를 인라인 CSS 스타일 속성으로 변환합니다. 이것이 React 구성 요소의 스타일을 지정하는 가장 좋은 방법은 아니지만 조건부 스타일을 요소에 적용 할 때 사용하는 것이 매우 편리하다는 것을 알았습니다. 예를 들어 다음은 텍스트의 절반 정도를 임의로 녹색 또는 빨간색으로 출력하는 구성 요소입니다.

// jsdrops.com/bx6
ConditionalStyle 클래스는 React.Component {
  render () {
    반품 (
      
        당신은 이것을 어떻게 좋아합니까?            );   } }
ReactDOM.render (
  <조건부 스타일 />,
  mountNode,
);

이 스타일의 논리는 바로 컴포넌트에 있습니다. 나는 그것을 좋아한다! 클래스 이름을 조건부로 사용하는 것보다 작업하기가 더 쉬우 며 전역 CSS 스타일 시트에서 해당 클래스 이름이 수행하는 작업을 추적 할 수 있습니다.

JSX는 템플릿 언어가 아닙니다

HTML을 다루는 일부 라이브러리는 템플릿 언어를 제공합니다. 루프와 조건이있는 "향상된"HTML 구문으로 동적 뷰를 작성합니다. 그런 다음이 라이브러리는 JavaScript를 사용하여 템플릿을 DOM 작업으로 변환합니다. 그런 다음 브라우저에서 DOM 작업을 사용하여 향상된 HTML로 설명 된 DOM 트리를 표시 할 수 있습니다.

반응은 그 단계를 제거했다. React 애플리케이션을 사용하여 브라우저에 템플릿을 전혀 보내지 않습니다. React API로 설명 된 객체 트리를 보냈습니다. React는 이러한 객체를 사용하여 원하는 DOM 트리를 표시하는 데 필요한 DOM 작업을 생성합니다.

HTML 템플리트가 사용되면 라이브러리는 애플리케이션을 문자열로 구문 분석합니다. React 애플리케이션은 객체 트리로 구문 분석됩니다.

JSX는 템플릿 언어처럼 보이지만 실제로는 그렇지 않습니다. HTML 템플릿과 유사한 구문으로 React의 객체 트리를 나타낼 수있는 JavaScript 확장 일뿐입니다. 브라우저는 JSX를 전혀 다루지 않아도되며 React도 처리하지 않아도됩니다! 컴파일러 만 수행합니다. 우리가 브라우저에 보내는 것은 템플릿과 JSX가없는 코드입니다.

예를 들어 위에서 본 todos 배열의 경우 템플릿 언어를 사용하여 해당 배열을 UI에 표시하려면 다음과 같은 작업을 수행해야합니다.

      <할 일 목록의 각 할일 %%>     
  • <% = todo.body %>   <% 끝 동안 %>
<% %>는 동적으로 향상된 부분을 나타내는 하나의 구문입니다. {{}} 구문이 표시 될 수도 있습니다. 일부 템플릿 언어는 향상된 논리에 특수 속성을 사용합니다. 일부 템플릿 언어는 공백 들여 쓰기를 사용합니다 (오프사이드 규칙).

todos 배열이 변경 될 때 (그리고 템플릿 언어로 DOM에서 렌더링 된 것을 업데이트해야하는 경우) 해당 템플리트를 다시 렌더링하거나 DOM 트리에서 todos 배열의 변경 사항을 반영해야하는 위치를 계산해야합니다. .

React 애플리케이션에는 템플릿 언어가 전혀 없습니다. 대신 JSX를 사용합니다.

      {todos.map (todo =>     
  • {todo.body}   )}

브라우저에서 사용하기 전에 다음으로 번역됩니다.

React.createElement (
  "ul",
  없는,
  todos.map (todo =>
    React.createElement ( "li", null, todo.body)
  ),
);

React는이 객체 트리를 가져 와서 DOM 요소 트리로 변환합니다. 우리의 관점에서, 우리는이 나무로 끝났습니다. Google은 이에 대한 조치를 관리하지 않습니다. 우리는 단지 todos 배열 자체에서 작업을 관리합니다.

클래스를 사용하여 컴포넌트 만들기

React는 JavaScript 클래스 구문을 통해 컴포넌트 작성을 지원합니다. 다음은 클래스 구문으로 작성된 동일한 Button 구성 요소 예제입니다.

// jsdrops.com/bx7
class Button은 React.Component {를 확장합니다
  render () {
    반품 (
      
// 사용 (동일한 구문)
ReactDOM.render (

이 구문에서는 React 최상위 API의 기본 클래스 중 하나 인 React.Component를 확장하는 클래스를 정의합니다. 클래스 기반 React 컴포넌트는 최소한 render라는 인스턴스 메소드를 정의해야합니다. 이 render 메서드는 구성 요소에서 인스턴스화 된 객체의 출력을 나타내는 요소를 반환합니다. 를 렌더링하여 Button 클래스 기반 구성 요소를 사용할 때마다 React는이 클래스 기반 구성 요소에서 객체를 인스턴스화하고 해당 객체의 표현을 사용하여 DOM 요소를 만듭니다. 또한 DOM 렌더링 요소를 클래스에서 생성 한 인스턴스와 연결합니다.

렌더링 된 JSX에서 this.props.label을 어떻게 사용했는지 주목하십시오. 모든 컴포넌트는 인스턴스화 될 때 해당 컴포넌트의 요소에 전달 된 모든 값을 보유하는 props라는 특수 인스턴스 특성을 가져옵니다. 함수 구성 요소와 달리 클래스 기반 구성 요소의 렌더링 함수는 인수를받지 않습니다.

함수 대 클래스

React에서 제한되었던 기능으로 생성 된 컴포넌트. 구성 요소를 "상태 저장"으로 만드는 유일한 방법은 클래스 구문을 사용하는 것입니다. 2019 년 초에 릴리스 된 React 버전 16.8로 시작하는 "React Hooks"릴리스로 변경되었습니다. React 후크 릴리스는 함수 구성 요소를 상태 저장 (및 기타 많은 기능 제공)하는 새로운 API를 도입했습니다.

이 새로운 API를 사용하면 일반적으로 React로 수행되는 대부분의 작업을 함수로 수행 할 수 있습니다. 클래스 기반 구문은 고급 및 매우 드문 경우에만 필요합니다.

새 API가 이전 API를 천천히 대체 할 것이라고 생각하지만 이것이 유일한 API 사용을 권장하는 것은 아닙니다 (가능한 경우에만).

대규모 응용 프로그램에서 두 API를 모두 사용했으며 여러 가지 이유로 새로운 API가 이전 API보다 훨씬 우수하지만 개인적으로 가장 중요하다고 생각하는 API는 다음과 같습니다.

  • 클래스 "인스턴스"및 해당 암시 적 상태로 작업 할 필요는 없습니다. 각 렌더에서 새로 고쳐지는 간단한 기능을 사용합니다. 상태는 명시 적으로 선언되어 있으며 아무것도 숨겨져 있지 않습니다. 이 모든 것은 기본적으로 코드에서 놀라움이 덜 발생한다는 것을 의미합니다.
  • 관련 상태 저장 논리를 그룹화하여 독립적 인 구성 가능 및 공유 가능 단위로 분리 할 수 ​​있습니다. 따라서 복잡한 구성 요소를 더 작은 부품으로 쉽게 분할 할 수 있습니다. 또한 구성 요소 테스트가 쉬워집니다.
  • 구성 요소 트리에서 계층 적 "중첩"을 사용할 필요없이 선언적인 방식으로 상태 저장 논리를 사용할 수 있습니다.

클래스 기반 구성 요소는 예측 가능한 미래를위한 React의 일부가 될 것이지만, 생태계의 새로운 이민자로서 기능과 후크로 순전히 시작하고 새로운 API를 배우는 데 집중하는 것이 합리적이라고 생각합니다 이미 클래스를 사용하는 코드베이스로 작업해야합니다).

구성 요소와 요소
React 안내서와 자습서에서“component”와“element”라는 단어가 섞여있을 수 있습니다. React 학습자는 중요한 차이점을 이해해야한다고 생각합니다.
반응 구성 요소는 템플릿입니다. 청사진. 글로벌 정의. 이것은 함수 또는 클래스 일 수 있습니다 (렌더 메소드 사용).
반응 요소는 구성 요소에서 반환되는 것입니다. 컴포넌트가 나타내는 DOM 노드를 가상으로 설명하는 객체입니다. 함수 구성 요소의 경우이 요소는 함수가 리턴하는 오브젝트이고 클래스 구성 요소의 경우 요소는 구성 요소의 render 메소드가 리턴하는 오브젝트입니다. 반응 요소는 브라우저에 표시되지 않습니다. 그것들은 단지 기억에있는 물체 일 뿐이며 그것에 대해 아무것도 바꿀 수 없습니다.
React는 브라우저로 렌더링해야하는 DOM 요소 트리를 파악하기 위해 내부적으로 객체를 생성, 업데이트 및 파괴합니다. 클래스 컴포넌트로 작업 할 때 브라우저에서 렌더링 한 DOM 요소를 컴포넌트 인스턴스라고하는 것이 일반적입니다. 동일한 구성 요소의 여러 인스턴스를 렌더링 할 수 있습니다. 인스턴스는 클래스 기반 구성 요소 내에서 사용하는 "this"키워드입니다. 클래스에서 인스턴스를 수동으로 만들 필요는 없습니다. React의 기억에 어딘가에 있다는 것을 기억하면됩니다. 함수 컴포넌트의 경우 React는 함수 호출을 사용하여 렌더링 할 DOM 요소를 결정합니다.

구성 요소의 장점

"구성 요소"라는 용어는 다른 많은 프레임 워크와 라이브러리에서 사용됩니다. 맞춤 요소 및 HTML 가져 오기와 같은 HTML5 기능을 사용하여 기본적으로 웹 구성 요소를 작성할 수도 있습니다.

기본적으로 작업하든 React와 같은 라이브러리를 통해 작업하든 구성 요소에는 많은 장점이 있습니다.

먼저 구성 요소를 사용하면 코드를보다 읽기 쉽고 작업하기 쉽게 만들 수 있습니다. 이 UI를 고려하십시오.


 

이 UI는 무엇을 나타 냅니까? HTML을 말하면 여기에서 HTML을 빠르게 구문 분석하고 "클릭 할 수있는 이미지입니다"라고 말할 수 있습니다.이 UI를 구성 요소로 변환하는 경우 이름을 ClickableImage로 지정할 수 있습니다!

<클릭 가능한 이미지 />

상황이 복잡해지면 HTML 구문 분석이 어려워 져 구성 요소를 통해 편안한 언어를 사용하여 UI가 무엇을 나타내는 지 빠르게 이해할 수 있습니다. 더 큰 예는 다음과 같습니다.

<트위트 박스>
  
  <남은 캐릭터 />
  <트위터 버튼 />

실제 HTML 코드를 보지 않고이 UI가 무엇을 나타내는 지 정확히 알고 있습니다. 또한 나머지 문자 섹션의 출력을 수정해야하는 경우 정확히 어디로 가야하는지 알고 있습니다.

React 구성 요소는 동일한 응용 프로그램과 여러 응용 프로그램에서 재사용 할 수도 있습니다. 예를 들어, 다음은 ClickableImage 구성 요소의 가능한 구현입니다.

const ClickableImage = ({href, src}) => {
  반품 (
    
      
    
  );
};

href 및 src props에 대한 변수가 있으면이 구성 요소를 재사용 할 수 있습니다. 예를 들어,이 컴포넌트를 사용하기 위해 소품 세트로 렌더링 할 수 있습니다 :

그리고 다른 소품 세트를 사용하여 재사용 할 수 있습니다.

함수형 프로그래밍에는 순수한 함수라는 개념이 있습니다. 이것들은 기본적으로 외부 상태로부터 보호됩니다. 동일한 입력을 주면 항상 동일한 출력을 얻습니다.
React 컴포넌트가 정의 외부에있는 것에 의존하지 않거나 수정하는 경우 (예를 들어, 글로벌 변수를 사용하지 않는 경우) 해당 컴포넌트에 순수 레이블을 지정할 수 있습니다. 순수한 구성 요소는 아무런 문제없이 재사용 될 가능성이 더 높습니다.

뷰를 나타내는 컴포넌트를 만듭니다. ReactDOM의 경우 정의한 React 컴포넌트는 HTML DOM 노드를 나타냅니다. 위의 ClickableImage 구성 요소는 두 개의 중첩 된 HTML 요소로 구성되었습니다.

브라우저에서 HTML 요소를 내장 컴포넌트로 생각할 수 있습니다. 또한 자체 사용자 정의 구성 요소를 사용하여 더 큰 구성 요소를 구성 할 수도 있습니다. 예를 들어 검색 엔진 목록을 표시하는 구성 요소를 작성해 보겠습니다.

const SearchEngines = () => {
  반품 (
    
                     ); };

ClickableImage 구성 요소를 사용하여 SearchEngines 구성 요소를 어떻게 구성했는지 참고하십시오!

또한 데이터를 변수로 추출하고 해당 변수와 함께 작동하도록 설계하여 SearchEngines 구성 요소를 재사용 할 수 있습니다.

예를 들어 다음과 같은 형식으로 데이터 배열을 도입 할 수 있습니다.

const 데이터 = [
  {href : "http://google.com", src : "google.png"},
  {href : "http://bing.com", src : "bing.png"},
  {href : "http://yahoo.com", src : "yahoo.png"}
];

그런 다음 가 작동하도록하기 위해 객체 목록에서 ClickableImage 구성 요소 목록으로 데이터 배열을 매핑하면됩니다.

const SearchEngines = ({엔진}) => {
  반품 (
    <목록>
      {engines.map (engine => )}
    
  );
};
ReactDOM.render (
 ,
 document.getElementById ( "mountNode")
);

이 SearchEngine은 Google에 제공하는 모든 검색 엔진 목록과 함께 사용할 수 있습니다.

후크 란 정확히 무엇입니까?

React 컴포넌트의 훅은 특수 함수에 대한 호출입니다. 모든 후크 기능은 "사용"이라는 단어로 시작합니다. 이들 중 일부는 useState와 같은 상태 저장 요소가있는 함수 구성 요소를 제공하는 데 사용될 수 있고, 다른 요소는 useEffect와 같은 부작용을 관리하거나 함수 및 오브젝트 (예 : useCallback)를 캐시 / 메모리 화하는 데 사용될 수 있습니다. 갈고리는 매우 강력하며 하늘은 당신이 할 수있는 일에 한계가 있습니다.

반응 후크 기능은 기능 구성 요소 만 사용할 수 있습니다. 클래스 구성 요소에는 사용할 수 없습니다.

기본 useState 후크의 예를 보려면 위의 Button 구성 요소가 클릭 이벤트에 응답하도록하겠습니다. "count"변수에서 클릭 횟수를 유지하고 해당 변수의 값을 렌더링하는 버튼의 레이블로 표시합니다.

const 버튼 = () => {
  카운트 = 0;
  반품 (
    
ReactDOM.render (<버튼 />, mountNode);

이 계수 변수는 예제를 소개하는 데 필요한 상태 요소입니다. UI가 의존 할 데이터 (표시하기 때문에)이며 시간이 지남에 따라 바뀌기 때문에 상태 요소입니다.

코드에서 변수를 정의 할 때마다 상태가 표시되며 해당 변수의 값을 변경할 때마다 해당 상태가 변경됩니다. 명심하십시오.

카운트 상태의 값을 변경하기 전에 이벤트에 대해 알아야합니다.

사용자 이벤트에 응답

"onEvent"속성을 가진 이벤트 핸들러를이 경우 버튼 요소에 추가 할 수 있습니다. 이것은 onClick, onMouseOver, onScroll, onSubmit 등일 수 있습니다.

여기서 필요한 것은 onClick 이벤트이며 대상 요소의 속성으로 정의합니다. 예를 들어, 버튼을 클릭 할 때마다 프로그램이 콘솔에 메시지를 기록하도록하려면 다음과 같이 할 수 있습니다.

const 버튼 = () => {
  카운트 = 0;
  반품 (
    
ReactDOM.render (<버튼 />, mountNode);

문자열을 사용하는 onClick 속성의 DOM 버전과 달리 React의 onClick 속성은 함수 참조를 사용합니다. 중괄호 안에 지정하십시오.

함수 func () {}

함수 클릭 (이름)을 onClick 핸들러로 전달한 방법에 주목하십시오. 거기에 func을 호출하지 않았습니다. 버튼을 클릭하면 반응이 기능을 호출합니다.

위의 Button 구성 요소에있는 onClick 이벤트의 경우, 호출 할 때 콘솔에 메시지를 출력하는 함수 정의를 "인라인"했습니다. 버튼을 클릭 할 때마다 onClick 핸들러 (인라인 화살표 기능)가 호출되고 해당 메시지가 표시됩니다.

이벤트 이름이 낙타의 경우에 유의하십시오. React에서 처리하는 모든 DOM 관련 속성은 낙타 케이스 여야합니다 (그렇지 않은 경우 React에 오류가 표시됨). 또한 React는 사용자 정의 HTML 속성 사용을 지원하며 모두 소문자 형식이어야합니다.
React의 일부 DOM 속성은 일반 DOM API에서 수행하는 것과 약간 다릅니다. 그 예로는 onChange 이벤트가 있습니다. 일반 브라우저에서는 일반적으로 양식 입력란 외부를 클릭하거나 탭을 클릭하면 시작됩니다. React에서 onChange는 양식 필드의 값이 변경 될 때마다 (추가 / 제거 될 때마다) 발생합니다.
React의 일부 속성 이름은 HTML과 다릅니다. 그 예로는 React의 className 속성이 있는데 이는 HTML에서 class 속성을 사용하는 것과 같습니다. React 속성과 DOM 속성의 차이점에 대한 전체 목록은 jscomplete.com/react-attributes를 참조하십시오.

상태 읽기 및 업데이트

상태 업데이트를 추적하고 가상 DOM 확산 및 실제 DOM 조정을 트리거하려면 React는 구성 요소 내에서 사용되는 모든 상태 요소에 대한 변경 사항을 알고 있어야합니다. 효율적인 방식으로이를 수행하려면 React는 컴포넌트에 도입 한 각 상태 요소에 대해 특수 getter 및 setter를 사용해야합니다. 여기서 useState 후크가 작동합니다. 그것은 상태 요소를 정의하고 getter와 setter를 돌려줍니다!

구현하려는 카운트 상태 요소에 필요한 것은 다음과 같습니다.

const [count, setCount] = React.useState (0);

useState 함수는 정확히 2 개의 항목이있는 배열을 반환합니다. 첫 번째 항목은 값 (getter)이고 두 번째 항목은 함수 (setter)입니다. 이 항목 이름을 지정하기 위해 배열 소멸을 사용했습니다. 원하는 이름을 지정할 수 있지만 [name, setName]이 규칙입니다.

첫 번째 항목 "value"는 문자열, 숫자, 배열 또는 기타 유형일 수 있습니다. 이 경우에는 숫자가 필요했고 그 숫자를 0으로 초기화해야했습니다. React.useState에 대한 인수는 상태 요소의 초기 값으로 사용됩니다.

두 번째 항목 "function"은 호출 될 때 state 요소의 값을 변경합니다 (필요한 경우 DOM 처리를 트리거 함). setCount 함수가 호출 될 때마다 React는 Button 구성 요소를 다시 렌더링하여 구성 요소에 정의 된 모든 변수 (카운트 값 포함)를 새로 고칩니다. setCount에 전달하는 인수는 count의 새로운 값이됩니다.

버튼의 레이블을 증가시키기 위해해야 ​​할 일은 onClick 이벤트 내에서 setCount 함수를 호출하고 현재 카운트 값을 1 씩 증가시키는 것입니다. 레이블 증가 버튼 예제의 전체 코드는 다음과 같습니다.

const 버튼 = () => {
  const [count, setCount] = useState (0);
  반품 (
    
ReactDOM.render (<버튼 />, mountNode);

계속해서 테스트 해보십시오. 버튼은 이제 클릭 할 때마다 레이블을 증가시킵니다.

UI 자체를 변경하기위한 조치를 구현하지 않은 방법에 주목하십시오. 대신, 우리는 메모리에서 JavaScript 객체를 변경하는 액션을 구현했습니다! 우리의 UI 구현은 기본적으로 React에게 버튼의 레이블이 항상 countobject의 값을 반영하기를 원한다고 알려주었습니다. 우리 코드는 DOM 업데이트를 수행하지 않았습니다. 반응했다.

const 키워드를 사용하여 변경되는 값이지만 카운트를 정의하는 방법에 주목하십시오! 우리의 코드는 그 값을 바꾸지 않을 것입니다. React는 새로운 Button 함수 호출을 사용하여 새로운 상태의 UI를 렌더링합니다. 새로운 호출에서 useState 함수 호출은 새로운 새로운 카운트 값을 제공합니다.

useState 함수는 놀이터에서 전 세계적으로 사용 가능합니다. 이것은 React.useState의 별명 일뿐입니다. 코드에서 명명 된 가져 오기를 사용하여 모듈 범위에서 useState를 직접 사용할 수 있습니다.
import React, {useState}에서 'react';

이 힘을 높이려면 몇 가지 예가 더 필요합니다. 이 기본 예제에 더 많은 기능을 추가하겠습니다. 버튼이 많고 모두 하나의 공유 카운트 값을 늘리도록합시다.

여러 컴포넌트로 작업

지금까지 가지고있는 Button 구성 요소를 두 가지 구성 요소로 나누겠습니다.

  • 버튼 요소를 나타내지 만 정적 레이블이있는 Button 구성 요소를 유지하십시오.
  • 카운트 값을 표시하려면 새 디스플레이 구성 요소를 추가하십시오.

새로운 디스플레이 구성 요소는 상태 나 상호 작용이없는 순수한 프리젠 테이션 구성 요소입니다. 그건 정상입니다 모든 React 컴포넌트가 상태 저장 후크를 갖거나 대화식이어야하는 것은 아닙니다.

const 디스플레이 = (props) => (
  
 여기서 COUNT 개의 값 ... 
);

디스플레이 구성 요소의 책임은 단순히 소품으로받을 값을 표시하는 것입니다. 예를 들어, 사전 요소가 값을 호스팅하는 데 사용되었다는 사실이 그 책임의 일부입니다. 이 응용 프로그램의 다른 구성 요소는 그것에 대해 말하지 않습니다!

형제 구성 요소 렌더링

이제 렌더링 할 버튼과 디스플레이라는 두 가지 요소가 있습니다. 다음과 같이 서로 바로 옆에 렌더링 할 수 없습니다.

// 작동하지 않습니다
ReactDOM.render (<버튼 /> <디스플레이 />, mountNode);

JSX가 변환 될 때 각 요소가 함수 호출로 변환되므로 React에서 이와 같은 인접 요소를 렌더링 할 수 없습니다. 이 문제를 처리 할 수있는 몇 가지 옵션이 있습니다.

먼저 요소 배열을 ReactDOM.render에 전달하고 원하는 수의 React 요소를 해당 배열에 삽입 할 수 있습니다.

옵션 1

ReactDOM.render ([<버튼 />, <디스플레이 />], mountNode);

일반적으로 렌더링중인 모든 요소가 동적 소스에서 나오는 경우에 좋은 솔루션입니다. 그러나 여기서 수행하는 경우에는 적합하지 않습니다.

다른 옵션은 형제 React 요소를 다른 React 요소의 하위 요소로 만드는 것입니다. 예를 들어 div 요소로 묶을 수 있습니다.

옵션 # 2

ReactDOM.render (
  
    <버튼 />     <디스플레이 />   ,   mountNode );

React API는이 중첩을 지원합니다. 사실, 새로운 DOM 부모 노드를 도입하지 않고 이와 같은 여러 인접 요소를 묶어야하는 경우 React에는 특별한 객체가 있습니다. React.Fragment를 사용할 수 있습니다.

옵션 # 3

ReactDOM.render (
  <반응식>
    <버튼 />
    <디스플레이 />
  ,
  mountNode
);

이 사례는 React에서 매우 일반적이므로 JSX 확장에는 단축키가 있습니다. React.Fragment를 입력하는 대신 빈 태그 <> 를 사용할 수 있습니다.

옵션 # 3 +

ReactDOM.render (
  <>
    <버튼 />
    <디스플레이 />
  ,
  mountNode
);

빈 태그는 React.Fragment 구문으로 변환됩니다. 이 구문을 사용하여 예제를 계속하겠습니다.

그러나 ReactDOM.render에 대한 첫 번째 인수를 방금 수행 한 중첩 트리 대신 단일 컴포넌트 호출로 만들어야합니다. 이것은 본질적으로 코드 품질 환경 설정입니다. 구성 요소 계층 구조, 이름 및 관계에 대해 생각하게합니다. 다음에 해봅시다.

최상위 컴포넌트

Button 및 Display 구성 요소를 모두 호스팅하는 최상위 구성 요소를 소개하겠습니다. 이제 문제는이 새로운 부모 컴포넌트의 이름을 어떻게 정해야 하는가입니다.

믿거 나 말거나, 컴포넌트와 상태 / 프로스 요소의 이름을 짓는 것은 컴포넌트가 작동하고 수행하는 방식에 영향을 미치는 매우 어려운 작업입니다. 올바른 이름을 사용하면 올바른 디자인 결정을 내릴 수 있습니다. 시간을내어 React 앱에 도입 한 모든 새로운 이름을 생각하십시오.

이 새로운 상위 컴포넌트는 표시된 카운트를 증가시키는 버튼이있는 디스플레이를 호스팅하므로 카운트 값 관리자라고 생각할 수 있습니다. 이름을 CountManager로 지정하겠습니다.

const CountManager = () => {
  반품 (
    <>
      <버튼 />
      <디스플레이 />
    
  );
};
ReactDOM.render (, mountNode);

새로운 디스플레이 구성 요소에 카운트 값을 표시하므로 더 이상 카운트 값을 버튼의 레이블로 표시 할 필요가 없습니다. 대신 레이블을 "+1"과 같은 것으로 변경할 수 있습니다.

const 버튼 = () => {
  반품 (
    

더 이상 가질 수 없기 때문에 Button 구성 요소에서 state 요소도 제거했습니다. 새로운 요구 사항으로 인해 Button 및 Display 구성 요소 모두 카운트 상태 요소에 액세스해야합니다. 디스플레이 구성 요소가 표시하고 Button 구성 요소가이를 업데이트합니다. 구성 요소가 형제 구성 요소가 소유 한 상태 요소에 액세스해야하는 경우, 한 가지 해결책은 해당 상태 요소를 한 레벨 위로 "상승"하여 상위 구성 요소 내에 정의하는 것입니다. 이 경우 부모는 방금 소개 한 CountManager 구성 요소입니다.

상태를 CountManager로 옮기면 컴포넌트 소품을 사용하여 부모에서 자식으로 데이터를 "흐르게"할 수 있습니다. 이것이 디스플레이 구성 요소에 카운트 값을 표시하기 위해해야 ​​할 일입니다.

const 표시 = ({content}) => (
  
 {content} 
);
const CountManager = () => {
  const [count, setCount] = useState (0);
  반품 (
    <>
      <버튼 />
      <표시 내용 = {count} />
    
  );
};
ReactDOM.render (, mountNode);

CountManager에서 Button 구성 요소와 동일한 useState 줄을 어떻게 사용했는지 참고하십시오. 우리는 동일한 상태 요소를 해제하고 있습니다. 또한 소품을 통해 카운트 값을 디스플레이 구성 요소로 흘렀을 때 다른 이름 (콘텐츠)을 사용했습니다. 그건 정상입니다 똑같은 이름을 사용할 필요는 없습니다. 실제로 경우에 따라 새로운 일반 이름을 도입하면 하위 컴포넌트가 재사용 성이 높아 지므로 하위 컴포넌트에 더 좋습니다. 카운트 이외의 다른 숫자 값을 표시하기 위해 디스플레이 구성 요소를 재사용 할 수 있습니다.

부모 구성 요소는 자녀에게 동작을 전달할 수 있으므로 다음에 수행해야합니다.

카운트 상태 요소는 이제 CountManager 구성 요소에 있으므로 업데이트를 처리하기 위해 해당 레벨의 함수가 필요합니다. 이 함수의 이름을 incrementCounter로 지정하겠습니다. 이 함수의 논리는 실제로 Button 구성 요소의 handleClick 함수에서 이전과 동일한 논리입니다. 새로운 incrementalCounter 함수는 CountManager 구성 요소 카운트 상태를 업데이트하여 이전 값을 사용하여 값을 증가시킵니다.

const CountManager = () => {
  // ....
  const incrementCounter = () => {
    setCount (수 + 1);
  }
  // ...
};

Button 구성 요소의 onClick 핸들러가 변경되어야합니다. CountManager 구성 요소에있는 incrementCounter 함수를 실행하려고하지만 구성 요소는 자체 기능에만 액세스 할 수 있습니다. 따라서 Button 구성 요소가 CountManager 구성 요소에서 incrementCounter 함수를 호출 할 수있게하려면 incrementCounter에 대한 참조를 소품으로 Button 구성 요소에 전달할 수 있습니다. 예, 소품은 데이터뿐만 아니라 기능도 보유 할 수 있습니다. 함수는 JavaScript의 객체 일 뿐이며 전달할 수있는 객체와 같습니다.

이 새로운 소품의 이름은 무엇이든 지정할 수 있습니다. clickAction이라는 이름을 지정하고 CountManager 구성 요소에서 정의한 함수에 대한 참조 인 incrementCounter 값을 전달합니다. 이 새로운 전달 된 동작을 onClick 핸들러 값으로 직접 사용할 수 있습니다. Button 구성 요소의 소품입니다.

const 버튼 = ({clickAction}) => {
  반품 (
    
// ...
const CountManager = () => {
  // ...
  반품 (
    
      

매우 강력한 무언가가 여기서 일어나고 있습니다. 이 clickAction 속성을 통해 Button 구성 요소는 CountManager 구성 요소의 incrementCounter 함수를 호출 할 수있었습니다. 이 버튼을 클릭하면 Button 구성 요소가 CountManager 구성 요소에 도달하여 "부모님, 계속해서 증가 카운터 동작을 호출하십시오"라고 말합니다.

실제로 CountManager 구성 요소는 여기에서 제어되는 요소이며 Button 구성 요소는 일반적인 규칙을 따릅니다. 코드를 지금 그대로 분석하면 Button 구성 요소가 클릭시 발생하는 상황에 대한 단서가없는 방법을 알게됩니다. 부모가 정의한 규칙을 따르고 일반 clickAction을 호출합니다. 부모는 그 일반적인 행동으로 들어가는 것을 제어합니다. 이것은 책임 격리 개념을 따릅니다. 여기의 각 구성 요소에는 특정 책임이 있으며 그에 중점을 둡니다.

다른 예는 디스플레이 구성 요소를보십시오. 관점에서 볼 때 카운트 값은 상태가 아닙니다. CountManager 구성 요소가 전달하는 소품입니다. 디스플레이 구성 요소는 항상 해당 소품을 표시합니다. 이것은 또한 책임의 분리입니다.

이러한 구성 요소의 설계자로서 책임 수준을 선택할 수 있습니다. 예를 들어, CountManager 구성 요소 자체의 카운트 값 부분을 표시하고 새로운 Display 구성 요소를 사용하지 않을 수 있습니다.

CountManager 구성 요소는 카운트 상태를 관리 할 책임이 있습니다. 그것은 우리가 결정한 중요한 디자인 결정이며 React 응용 프로그램에서 많은 것을 결정해야 할 결정입니다. 국가를 어디에서 정의합니까?

내가 따르는 관행은 공유 부모 노드에서 상태 요소에 액세스해야하는 모든 하위 요소에 가능한 한 가까운 상태 요소를 정의하는 것입니다. 이와 같은 작은 응용 프로그램의 경우 일반적으로 최상위 구성 요소 자체를 의미합니다. 더 큰 응용 프로그램에서 하위 트리는 최상위 루트 구성 요소에 정의 된 전역 상태 요소에 의존하지 않고 자체 상태 "분기"를 관리 할 수 ​​있습니다.

최상위 구성 요소는 다른 모든 구성 요소의 상위 항목이므로 공유 응용 프로그램 상태 및 작업을 관리하는 데 널리 사용됩니다. 최상위 구성 요소에서 상태 요소를 업데이트하면 전체 구성 요소 트리가 메모리에 다시 렌더링되므로이 디자인에주의하십시오.

지금까지이 예제의 전체 코드는 다음과 같습니다.

// jsdrops.com/bx8
const 버튼 = ({clickAction}) => {
  반품 (
    
const 표시 = ({content}) => (
  
 {content} 
);
const CountManager = () => {
  const [count, setCount] = useState (0);
  const incrementCounter = () => {
    setCount (수 + 1);
  };
  반품 (
    
      

컴포넌트 재사용 가능

구성 요소는 모두 재사용 가능성에 관한 것입니다. Button 구성 요소를 변경하여 재사용 할 수있게하여 전체 개수를 1이 아닌 모든 값으로 증가시킬 수 있습니다.

CountManager 구성 요소에 Button 요소를 더 추가하여이 새로운 기능을 테스트 해 보겠습니다.

const CountManager = () => {
  // ..
  반품 (
    <>
      

위에서 렌더링 된 모든 Button 요소에는 현재 +1 레이블이 있으며 카운트는 1 씩 증가합니다. 각 단추에 고유 한 다른 레이블을 표시하고 특정 값에 따라 다른 동작을 수행하도록하려고합니다. 그들 각각에게. 소품으로 React 요소에 값을 전달할 수 있습니다.

각 버튼을 한 번 클릭 한 후 염두에 두어야 할 UI는 다음과 같습니다.

위의 스크린 샷에서 카운트는 0으로 시작했습니다. 1, 5, 10을 추가하여 16에 도달했습니다.

이 연습을 진행하기 전에 잠시 시간을내어 생각해보고 직접 구현해보십시오. 대부분 간단합니다. 힌트 : Button에 대한 새로운 소품 1 개를 소개해야합니다. 기회를주세요. 솔루션과 내 솔루션을 비교할 준비가되면 돌아 오십시오.

새로운 소품 추가

가장 먼저해야 할 일은 Button 구성 요소의 +1 레이블을 사용자 지정 가능한 레이블로 만드는 것입니다.

React 컴포넌트에서 사용자 정의 가능한 것을 만들기 위해 우리는 새로운 소품 (부모 컴포넌트가 제어 할 수있는)을 도입하고 컴포넌트가 그 값을 사용하도록합니다. 이 예에서는 Button 구성 요소에 새 소품으로 증가량 (1, 5, 10)을 받도록 만들 수 있습니다. 이름을 clickValue로 지정하겠습니다. CountManager에서 render 메소드를 변경하여 테스트하려는 값을이 새로운 prop에 전달할 수 있습니다.

반품 (
  <>
    

지금까지이 코드에 대한 몇 가지 사항에 유의하십시오.

  • 백작과 관련된 것으로 새 부동산의 이름을 지정하지 않았습니다. Button 구성 요소는 클릭 이벤트의 의미를 인식하지 않아도됩니다. 클릭 이벤트가 트리거 될 때이 clickValue를 전달하면됩니다. 예를 들어,이 새로운 속성 countValue의 이름을 지정하는 것은 최선의 선택이 아닙니다. 이제 Button 구성 요소에서 Button 요소가 카운트와 관련되어 있음을 이해하기 위해 코드를 읽습니다. 이렇게하면 Button 구성 요소의 재사용 성이 떨어집니다. 예를 들어, 동일한 Button 구성 요소를 사용하여 문자를 문자열에 추가하려는 경우 코드가 혼동 될 수 있습니다.
  • 중괄호를 사용하여 새 clickValue 속성 (clickValue = {5})의 값을 전달했습니다. 거기에 문자열을 사용하지 않았습니다 (clickValue = "5"). 이 값과 관련된 수학적 연산이 있기 때문에 (버튼을 클릭 할 때마다)이 값이 숫자 여야합니다. 문자열로 전달하면 추가 작업이 실행될 때 문자열을 숫자로 변환해야합니다.
React에서 숫자를 문자열로 전달하는 것은 일반적인 실수입니다. 더 많은 React 관련 실수에 대해서는이 기사를 참조하십시오.

동작 사용자 정의

CountManager 구성 요소에서 일반화해야 할 다른 항목은 incrementCounter 작업 함수입니다. 현재처럼 하드 코드 된 수 + 1 작업을 가질 수 없습니다. Button 구성 요소에서 수행 한 작업과 유사하게 함수를 일반화하려면 인수를 받고 해당 인수의 값을 사용합니다. 예를 들면 다음과 같습니다.

incrementCounter = (incrementValue) => {
  setCount (count + incrementValue);
};

이제 Button 구성 요소가 clickValue 소품을 레이블로 사용하고 clickValue를 인수로 사용하여 onClick 액션을 호출하도록해야합니다.

const 버튼 = ({clickValue, clickAction}) => {
  반품 (
    

버튼의 clickValue에 바인딩하기 위해 onClick 소품을 인라인 화살표 기능으로 감싸는 방법에 주목하십시오. 이 새로운 화살표 함수에 대한 JavaScript 클로저가이를 처리합니다.

세 개의 버튼은 세 개의 다른 클릭 값으로 증가합니다. 이 예제 코드는 jsdrops.com/bx9에서 확인할 수 있습니다.

사용자의 입력을 수락

트위터의 트윗 양식과 같이 텍스트 영역에 사용자가 입력 한 문자를 계산해야한다고 상상해보십시오. 사용자가 입력하는 각 문자마다 새로운 문자 수로 UI를 업데이트해야합니다.

문자 수에 대한 자리 표시 자 div가있는 텍스트 영역 입력 요소를 표시하는 구성 요소는 다음과 같습니다.

// jsdrops.com/bx10
const CharacterCounter = () => {
  반품 (