분류 Reactjs

React 101 : 모든 초보자가 알아야 할 것들-1 부

컨텐츠 정보

  • 조회 284 (작성일 )

본문

올바른 방법으로 React.js 애플리케이션 작성


따라서 동료들과의 긴 토론과 더 긴 온라인 연구-스택 오버플로 및 그렇지 않은 것-마침내 React와 함께하기로 결정했습니다. 다가오는 프로젝트를 오랫동안 고려한 후 Angular, Vue 및 Jquery와 같은 프레임 워크 및 라이브러리를 성공적으로 무시했습니다. 축하합니다. 성공적으로 영향을 받았습니다.


다음 몇 주 동안, 나는 모든 블로그와 매체 기사를 깊이 파고 들었습니다. 그것이 제가 처음 결론을 내린 곳인 Angular 2 또는 React입니다. 앞으로 나는 반응이 디자인 된 방식에 대해 독특한 것을 발견했습니다 .JS 내부의 HTML? 시원한. 마지막으로 Angular.js 지시문 및 기타 프레임 워크 구성 요소에 대한 초기 좌절은 보상이 되었으며 결국 React에 블로그를 제공하기로 결정했습니다. 말할 것도 없이 Angular 2는 나쁘지 않습니다. 나는 그 당시 React와 함께 가기로 결정했습니다. 온라인 영향 (Dan Abramov는 여전히 긍정적 인 영향을 미칩니다.


https://contextneutral.com/story/react-101-things-every-beginner-should-know 


이제 기사로 돌아와서 React 앱을 작성하기 시작한 지 오래되지 않았으며 초보자를 대상으로 기사를 작성할 자격이 있다고 생각하기 때문에 이 이야기를 들었습니다. 이 기사에는 React 로이 블로그를 작성하기 시작했을 때 누군가로 부터 얻은 팁이 포함되어 있습니다 (예, 여전히 많은 문제가 있습니다!). 지난 2 년간의 경험을 바탕으로 모든 단일 요점을 작성했습니다. 


1. 컴포넌트를 전용 폴더에 보관하십시오 


나는 Angular와 함께 가기로 선택하지 않았을 수도 있지만 (ng 2, 간단히) 구조화 아이디어를 빌렸습니다. ng 2에서는 이와 같은 CLI를 사용하여 구성 요소를 만들 때

ng generate component "component-name"

.ts, .css, .spec.ts 및 .html 파일이 포함 된 구성 요소의 폴더를 만듭니다. 우리는 같은 패턴을 따릅니다. 구성 요소는 구성 요소와 이름이 같은 전용 폴더 안에 있어야 하며 하위 구성 요소는 부모 폴더 내에서 동일한 패턴을 계속 유지합니다. 은혜? 코드 구성 요소를 깔끔하게 정리할 수 있습니다.


내가 빌린 또 다른 것은 각 구성 요소에 대한 CSS 파일을 유지하거나 각 .js 파일에 대해 반응하는 아이디어입니다. 이렇게 하면 다른 구성 요소 스타일을 손상 시키지 않고 구성 요소를 스타일링 하는 데 집중할 수 있습니다. 또 하나의 이점은 구성 요소를 완전히 무시할 수 있으며 전체 클래스 크기에 추가되지 않는다는 것입니다. 우리는 실수로 사용하지 않은 CSS를 포함하지 않을 것입니다. 깔끔한가요? 또한 .css 파일은 js 구성 요소와 동일한 폴더에 있습니다. 이 구조가 마음에 들면 이것을 습관화 하도록 선택할 수 있습니다!


2. 소품과 국가의 차이점 


React로 시작했을 때 사람들은 종종 소품과 상태와 혼동됩니다. 이에 대한 가장 간단한 대답은 상태는 변경 가능하며 구성 요소 자체를 기반으로 하며 부모 또는 다른 구성 요소는 이를 만지거나 업데이트 할 수 없습니다.


반면 소품은 불변입니다-최종 (또는 상수) 값과 같이 구성 요소 자체 내에서 변경할 수 없습니다. 부모 구성 요소가 업데이트 할 때마다 업데이트 됩니다. 소품은 부모 구성 요소가 자식 구성 요소 또는 보다 사실적으로 명명된 바보 구성 요소에 데이터를 전달하는 방법입니다. 간단한 예제를 통해 props와 state가 어떻게 다른지 봅시다. 이것은 우리의 부모로, 사용자의 이름과 나이를 각각 포함하는 이름과 나이라는 두 개의 소품으로 Child를 렌더링 합니다.

class Parent extends React.Component {
  render() {
  return( <Child name={ 'Nilesh' }  age={ 23 } /> )
  }
}

반면에 하위 구성 요소는 다음과 같습니다.

class Child extends React.Component {
  render() {
    return (
  <div>
      <span>Username: { this.props.name } </span>
      <span>Age: { this.props.age } </span>
    </div>
)
  }
}

자식 구성 요소에 소품을 사용 했습니까? 소품은 렌더링 중에 부모가 설정하는 자식 구성 요소에 대한 특별한 특성에 지나지 않습니다. 자식은 이를 사용하여 렌더링 하는 동안 데이터 값을 설정할 수 있습니다. 소품이 계층 구조로 전달되면 그것을 수신하는 Child에 의해 변경 될 수 없습니다.


앞에서 말했듯이 상태는 구성 요소 자체가 부모 업데이트 소품 없이 변경 사항을 처리 할 수 ​​있도록 변경 가능하도록 설계되었습니다. 예를 들어 Child 구성 요소 내의 버튼을 클릭하면 구성 요소가 내부 변경 사항을 처리 할 수 있는 상태가 있으며 사용자 이름은 'Nilesh Singh'에서 'John Doe'로 변경해야 합니다. 자식 수준에서는 불변이기 때문에 소품. 우리는 이런 식으로 Child 안에 상태를 정의합니다.

class Child extends React.Component {
  constructor(props) {
   super(props)
   this.state = { username: 'Nilesh Singh' }
}
}

예, 상태는 모든 값을 키와 값으로 보유하는 JavaScript 객체입니다. 또한 생성 중에는 React가 생성 중에 null 또는 정의되지 않은 값을 피할 수 있도록 생성자 내에 상태를 항상 정의해야 합니다.


상태 초기화가 완료되면 구성 요소 내 어디에서나 사용할 수 있습니다. 이 사용자 이름 상태를 렌더에서 사용자 이름으로 설정하고 버튼 클릭시 수동으로 변경합니다.

handleClick(e) {
  this.setState(prevState => {
  return { username: 'John Doe' }
})
}
render() {
    return (
      <div>
        <span>Username: { this.state.username } </span>
        <span>Age: { this.props.age } </span>
        <button onClick={ this.handleClick.bind(this) }>Change Username</button>
      </div>
    )
}

버튼을 클릭하면 handleClick 함수가 호출되고 setState (...)라는 특수 메소드를 사용하여 현재 상태를 업데이트합니다. 그렇다면 왜 이것을 특별한 방법이라고 부릅니까? 메소드를 사용하지 않고 상태 객체의 username 속성을 간단히 업데이트 할 수 있습니다.


this.state.username = 'John Doe'

물론, 우리는 할 수는 있지만 UI 측면에서는 아무것도 바뀌지 않을 것입니다. 즉 <span />에서 텍스트가 'John Doe'로 전혀 바뀌지 않습니다. 단순히 다시 렌더링 하지 않고 단순히 값을 변경합니다. 다시 렌더링 하려면 setState (...) 메소드를 호출하여 사용자 이름을 'John Doe'로 업데이트 한 다음 컴포넌트의 render (...) 메소드를 호출합니다. UI의 가치 변화.


그러나 사용자 이름 값이 처음으로 변경 된 다음 동일하게 유지되면 반응은 무엇입니까? 결국 우리는 클릭 할 때마다 setState (...) 메소드를 호출합니다. 값이 변경되는지 여부. 글쎄, 이것은 React가 실제로 빛나는 부분입니다. 물론, setState가 호출 될 때마다 렌더링 메소드가 트리거 되지만 React는 먼저 가상 DOM을 빌드하여 실제 값 변경을 확인하고 기본 DOM과 일치시킨 후 차이가 감지되면 기본 DOM을 업데이트합니다. 가상 DOM 및 작동 방식에 대한 자세한 내용은 여기를 참조하십시오.


한 가지 더, Props와 State는 서로 값을 설정하는 데 사용될 수 있지만 이것이 서로의 장소에서 사용될 수 있다는 것을 의미하지는 않습니다. 각 상태 업데이트가 다시 렌더링을 트리거 할 때 개별 상태를 유지하고 상태 업데이트를 최소화하십시오. 변경되지 않은 값으로 인해 Native DOM이 변경되지 않더라도 Virtual DOM 자체가 일부 주기를 소비한다는 점에 주목할 가치가 있습니다. 구축 및 일치 (확산). 서로를 설정하는 데 사용되는 상태와 소품의 간단한 예는 다음과 같습니다.

render() {
  return  (<Child name={ this.state.name } />)
}

또는

class Child extends React.Component {
  constructor(props) {
  this.state = {
  username: this.props.name
}
}
}

아, 그렇습니다. 상태를 변경하면 구성 요소가 다시 렌더링 될뿐만 아니라 소품의 변경도 동일하게 트리거 됩니다.


3. 쓸모없는 용기를 피하고 대신 조각을 사용하십시오. 


React 애플리케이션에 컴포넌트 계층 구조가 필요한 경우가 있습니다. React에서 그렇게 하는 것은 쉽지만 종종 우리가 무시하는 한 가지는 HTML 호출의 구조입니다. 우리는 종종 계층 구조에서 목적을 달성하지 못하는 쓸모없는 컨테이너 HTML 태그를 유지합니다. 예를 들어

g Child라는 자식 구성 요소를 호출하는 부모 클래스가 있다고 가정합니다. 부모의 구조는 다음과 같습니다.

<div className="parent">
  <Child></Child>
</div>

자, 우리의 자식 구성 요소는 한 가지만 수행한다고 아이입니다. 그 텍스트 주위의 div는 텍스트를 제어하지 못하거나 클래스 또는 클래스에 바인딩 되어 있기 때문에 쓸모없는 것으로 판명되지만 어느 정도 유용하다고 입증되었지만 여기서는 그렇지 않습니다.

<div>
  Hi, This is a child!
</div>

따라서 상위 HTML이 그 안에 하위 HTML로 렌더링 된 후 최종 HTML은 다음과 같습니다.

<div className="parent">
  <div> <!-- Useless div -->
    Hi, This is a child!
  </div>
</div>

두 번째 div는 쓸모가 없습니다. 다음 아이를 제어 할 수는 없습니다. 본문. 우리는 그것을 무시할 수 있었지만 다시 각 구성 요소를 태그 안에 싸야 합니다. 물론 우리는 하지만 이 <div> 또는 다른 HTML 태그를 부모가 자식을 호출 할 때 해당 특수 반응 구성 요소의 내부 자식이 구성 요소 자체 없이 렌더링 되도록 하는 내부 React 구성 요소로 바꿀 수 있습니다. 이 특수 구성 요소를 단편이라고 합니다.


이제 이 Fragment가 포함 된 하위 컴포넌트는 다음과 같습니다.

<>
  Hi, This is a child!
<>

또는 위의 구문에 오류가 있는 경우 조각 대신이 구문을 사용할 수 있습니다. 그러나 먼저 모듈에서 Fragment를 가져 와야 합니다.

import { Fragment } from 'react';

<Fragment>
  Hi, This is a child!
</Fragment>

이제 부모님이 새로 업데이트 된 자식을 호출하면 완전히 렌더링 되면 다음과 같이 보일 것입니다.

<div className="parent">
  Hi, This is a child! 
</div>

쓸모없는 div가 성공적으로 제거되었습니다. 가상 DOM을 실제 DOM으로 변경하는 동안 React가하는 일은 Fragment 컴포넌트의 자식을 다음과 같이 반환한다는 것입니다.

render() {
  return this.props.children
}

이것은 쓸모없는 컨테이너 태그를 식별하고 이를 Fragments로 바꾸는 약간의 힘든 작업처럼 보일 수 있지만, 인터페이스가 거대한 계층 구조 크기를 가지고 있고 어려움을 겪을 때 장기적으로 가치가 있습니다.


4. 항상 컴포넌트의 이벤트 및 핸들러를 구독 취소하십시오. 


React를 사용하면 콜백 함수를 요구하는 onclick이 React에서 onClick이 됩니다.

<button onClick={ this.handleClick.bind(this) }>Click Me</button>

간단하고 사용하기 쉬운 것 같지 않습니까? 글쎄, React가 그것을 처리 할 때 합성 이벤트를 사용할 수 있다면 매우 간단하지만 우리가 그것을 얻지 못하면 어떻게 될까요?

componentDidMount() {
   window.addEventListener('resize', this.sizeChanged);
}
sizeChanged() {
  // size changed
console.log(window.innerWidth, window.innerHeight)
}

브라우저 창 크기가 변경 될 때마다 화면 크기를 읽을 수 있습니다. 그러나 이벤트 리스너가 컨텍스트에서 끝났거나 메모리 누수를 피하기 위해 구성 요소를 간단하게 수행 (또는 파괴) 한 후에는 항상 이벤트 리스너를 제거하십시오. componentWillUnmount에서 removeEventListener를 호출하여 이벤트 리스너를 제거 할 수 있습니다. 이는 구성 요소가 제거되거나 파괴 될 예정임을 나타냅니다.

componentWillUnmount() {
    window.removeEventListener('resize', this.sizeChanged)
}

타임 아웃 또는 간격도 마찬가지입니다. 더 이상 유용하지 않다고 생각되면 componentWillUnmount 또는 다른 수명 주기 방법에서 항상 제거하십시오. 이는 프로그래머가 앱에서 메모리 누수 가능성을 무시하고 앱을 빌드 할 때 흔히 저지르는 실수입니다.


5. 쓸모없는 수업을 피하십시오 


초보자가 일반적으로 저지르는 또 다른 실수는 모든 구성 요소가 클래스 여야 한다는 가정입니다. 반드시 그런 것은 아닙니다. 구성 요소가 전달 된 소품을 기반으로 HTML을 반환하는 것 이상을 수행하지 않으면 대신 함수를 사용하십시오. 이러한 설정은 기능적인 상태 비 저장 구성 요소라고도 합니다. 구성 요소는 단순한 일반 자바 스크립트 함수 반환 HTML이므로 상태를 가질 수 없기 때문입니다.


명심해야 할 또 하나의 사실은 상태와 함께 기능적 구성 요소로 수명 주기 메소드를 얻지 못하므로 구성 요소가 수명 주기 후크에 의존하거나 로컬 상태를 가져야 하는 경우 클래스 기반 구성 요소를 사용하도록 선택하십시오.


기능적인 stateless 구성 요소의 간단한 예는 다음과 같습니다.

function Child( props ) {
  return (
  <div>Hello from a stateless component: { props.name }</div>
  )
}

6. 프록시 활용 


동일한 머신에서 개발중인 로컬 API를 쿼리해야 하는 상황에 처할 수 있습니다. 포트 8080에서 dev 서버를 실행 중인 경우 http : // localhost : 8080으로 쿼리 할 수 ​​있습니다. 샘플 요청은 다음과 같습니다.

fetch('http://localhost:8080/api/my-endpoint')
  .then(res => res.json())
  .then(data => {
    console.log('Received:', data);
})

이러한 종류의 설정은 프로덕션 용 앱 빌드를 시작하거나 다른 엔드 포인트 URL을 모두 쿼리 해야 할 때까지 의미가 있습니다. 여기에 프록시가 들어옵니다. React는 반응 내에서 요청을 처리해야 하는 대체 엔드 포인트를 정의 할 수 있는 프록시 기능을 제공합니다. 깔끔하지 않습니까? 

package.json 파일에 프록시 속성을 추가하여 React로 프록시를 설정하고 대체 URL을 다음과 같은 값으로 설정할 수 있습니다.

{
  "name": "my-react-app",
  "version": "0.0.1",
  "private": true,
  "proxy": "http://localhost:6000", //this is where magic happens
  "dependencies": {
   ...
}
}

이는 프록시 엔드 포인트로만 이동하는 깨끗하고 체계적인 요청 구조를 유지하는 데 실제로 도움이 됩니다. React가 기본 경로가 있는 요청을 프록시 엔드 포인트 대신 프록시 엔드 포인트로 리디렉션 하는 인터셉터 (예 : Ng 2 인터셉터)로 생각하십시오. 위와 같이 프록시를 설정 한 후이 작업을 수행 할 수 있습니다


fetch('/api/my-endpoint')
  .then(res => res.json())
  .then(data => {
     console.log('Received:', data);
   })

요청은 http : // localhost : 6000으로 시작합니다. 예, 프록시를 package.json에 추가 한 후 npm start를 사용하여 반응을 다시 시작해야 합니다.


7. Create-React-App을 더 잘 사용하십시오 


대부분의 온라인 온라인 자습서 (일반적으로 이전 자습서)에서는 webpack, babel 등의 모든 구성을 설정하여 기본부터 React 학습을 시작하는 것이 좋습니다. 그것은 하나의 프로젝트에는 괜찮은 것 같습니다. 동의합니다. 마술을 일으키는 일에 대한 아이디어를 얻지 만 프로젝트에서 여러 프로젝트로 이동하면 동일한 구성을 복사하는 것이 고통스럽습니다. 다른 디렉토리에 파일을 반복해서 추가합니다. 또한 그러한 조직에서 더 이상 사용되지 않는 코드를 재사용 할 가능성이 높아지고 있습니다.


이러한 문제를 피하려면 Create-React-App CLI (명령 줄 인터페이스)를 사용하여 새 React 앱을 만드는 것이 좋습니다. Create-React-App 도구를 사용하여 React 프로젝트, 웹팩 및 babel 설정 및 기타 종속성 설치를 위한 완전한 초기 구조를 얻습니다. 전역 플래그와 함께 다음 npm 명령을 실행하면 도구를 전역 적으로 사용할 수 있습니다.

npm install -g create-react-app

완료되면 이 명령을 실행하여 (1) 이름이 my-react-app 인 앱을 만든 다음 (2) 도구로 만든 프로젝트 디렉토리를 이동 한 다음 마지막으로 (3) npm start로 React 앱을 시작하십시오.

create-react-app my-react-app
cd my-react-app/
npm start

아무것도 구성 할 필요가 없으며 도구가 모든 것을 처리합니다. 그러나 문제가 있습니다. 프로젝트가 상용구 및 웹팩으로 처리되고 다른 종속성 부풀림으로 정상 설정으로 돌아 가지 않으면 해당 설정으로 웹팩 또는 사전 설정 (바벨)을 실제로 변경할 수 없습니다 package.json 파일


Create-react-app는 당신에게 나갈 수 있는 능력을 제공합니다. 다음과 같이 일반 설정으로 돌아갈 수 있습니다.

npm run eject

그러나 나는 그렇지 않으면 제안합니다-create-react-app 도구 만 사용하십시오. 여러 구성 파일을 관리하거나 업데이트 할 때마다 오버 헤드를 가져 오거나 매번 반응하거나 패키지를 깨끗하게 유지하고 유용한 메타 데이터로 로드 하지 마십시오. 시스템 (도구)에서 다른 작업을 처리 할 수 ​​있습니다.


# 다음은? 


이 7 가지 방법 중 6 가지 방법은 선택 사항이지만 보다 효율적인 React 앱을 구축하려면 정기적으로 사용하는 것이 좋습니다. 이것들은 처음에는 많은 것처럼 보일지 모르지만 일단 익숙해지면 많은 시간과 자원을 절약 할 수 있다고 생각합니다.