이 기사에 담긴 모든 기본적인 React.js 개념

업데이트 : 이 기사는 이제 제 책“React.js Beyond The Basics”의 일부입니다. jscomplete.com/react-beyond-basics에서이 콘텐츠의 업데이트 된 버전과 React에 대한 자세한 내용을 읽어보십시오 .

이 글은 React가 무엇인지, 왜 배워야하는지에 대해서는 다루지 않을 것입니다. 대신, 이것은 이미 JavaScript에 익숙하고 DOM API의 기초를 아는 사람들을위한 React.js의 기초에 대한 실용적인 소개입니다.

아래의 모든 코드 예제는 참조 용으로 레이블이 지정되어 있습니다. 그것들은 순전히 개념의 예를 제공하기위한 것입니다. 대부분은 훨씬 더 나은 방식으로 쓸 수 있습니다.

기본 # 1 : React는 구성 요소에 관한 것입니다.

React는 재사용 가능한 구성 요소의 개념을 중심으로 설계되었습니다. 작은 구성 요소를 정의하고 함께 결합하여 더 큰 구성 요소를 형성합니다.

작거나 큰 모든 구성 요소는 다른 프로젝트에서도 재사용이 가능합니다.

가장 단순한 형태의 React 컴포넌트는 평범한 JavaScript 함수입니다.

// Example 1 // //jscomplete.com/repl?j=Sy3QAdKHW function Button (props) { // Returns a DOM element here. For example: return {props.label}; } // To render the Button component to the browser ReactDOM.render(, mountNode)

버튼 레이블에 사용되는 중괄호는 아래에 설명되어 있습니다. 지금은 걱정하지 마십시오. ReactDOM나중에 설명 하겠지만이 예제와 앞으로 나올 모든 코드 예제를 테스트하려면 위의 render함수가 필요합니다.

두 번째 인수 ReactDOM.render는 React가 인수하고 제어 할 대상 DOM 요소입니다. jsComplete React Playground에서 특수 변수를 사용할 수 있습니다 mountNode.

React.js 용 JavaScript REPL 및 플레이 그라운드

구성없이 브라우저에서 최신 JavaScript 및 React.js 코드 테스트 jscomplete.com/react

예제 1에 대한 다음 사항에 유의하십시오.

  • 구성 요소 이름은 대문자로 시작합니다. 이것은 HTML 요소와 React 요소의 혼합을 다룰 것이기 때문에 필요합니다. 소문자 이름은 HTML 요소 용으로 예약되어 있습니다. 실제로 React 컴포넌트의 이름을 "버튼"으로 지정하고 ReactDOM이 함수를 무시하고 일반 빈 HTML 버튼을 렌더링하는 방법을 확인하십시오.
  • 모든 구성 요소는 HTML 요소와 마찬가지로 속성 목록을받습니다. React에서이 목록은 props 라고 합니다. 함수 구성 요소를 사용하면 이름을 지정할 수 있습니다.
  • Button위 의 함수 구성 요소 의 반환 된 출력에 HTML처럼 보이는 것을 이상하게 작성했습니다 . 이것은 JavaScript도 HTML도 아니며 React.js도 아닙니다. 그러나 그것은 매우 인기가있어서 React 애플리케이션의 기본값이되었습니다. JSX 라고 하며 JavaScript 확장입니다. JSX는 또한 타협입니다 ! 계속해서 위의 함수 내에서 다른 HTML 요소를 반환하고 모두 지원되는지 확인합니다 (예 : 텍스트 입력 요소 반환).

기초 # 2 : JSX의 흐름은 무엇입니까?

위의 예제 1은 다음과 같이 JSX없이 순수한 React.js로 작성할 수 있습니다.

// Example 2 - React component without JSX // //jscomplete.com/repl?j=HyiEwoYB- function Button (props) { return React.createElement( "button", { type: "submit" }, props.label ); } // To use Button, you would do something like ReactDOM.render( React.createElement(Button, { label: "Save" }), mountNode );

createElement함수는 React 최상위 API의 주요 기능입니다. 해당 레벨에서 배워야 할 총 8 가지 중 하나입니다. 이것이 React API가 얼마나 작은 지입니다.

document.createElement태그 이름으로 지정된 요소를 생성하는 기능이 있는 DOM 자체와 매우 유사하게 React의 createElement기능은 수행 할 수있는 상위 수준의 기능 document.createElement이지만 React 구성 요소를 나타내는 요소를 생성하는 데 사용할 수도 있습니다. Button위의 예제 2 에서 구성 요소를 사용할 때 후자를 수행했습니다 .

와 달리 document.createElementReact 는 생성 된 요소 createElement자식 을 나타 내기 위해 두 번째 인수 이후에 동적 수의 인수를받습니다 . 그래서 createElement실제로 나무를 만듭니다 .

그 예는 다음과 같습니다.

// Example 3 - React’s createElement API // //jscomplete.com/repl?j=r1GNoiFBb const InputForm = React.createElement( "form", { target: "_blank", action: "//google.com/search" }, React.createElement("div", null, "Enter input and click Search"), React.createElement("input", { name: "q", className: "input" }), React.createElement(Button, { label: "Search" }) ); // InputForm uses the Button component, so we need that too: function Button (props) { return React.createElement( "button", { type: "submit" }, props.label ); } // Then we can use InputForm directly with .render ReactDOM.render(InputForm, mountNode);

위의 예에 대한 몇 가지 사항에 유의하십시오.

  • InputFormReact 컴포넌트가 아닙니다. 그것은 단지 React 요소 입니다. 이것이 우리가 ReactDOM.render호출 에서 직접 사용한 이유 입니다. />.
  • The React.createElement function accepted multiple arguments after the first two. Its list of arguments starting from the 3rd one comprises the list of children for the created element.
  • We were able to nest React.createElement calls because it’s all JavaScript.
  • The second argument to React.createElement can be null or an empty object when no attributes or props are needed for the element.
  • We can mix HTML element with React elements.
  • React’s API tries to be as close to the DOM API as possible, that’s why we use className instead of class for the input element. Secretly, we all wish the React’s API would become part of the DOM API itself. Because, you know, it’s much much better.

The code above is what the browser understands when you include the React library. The browser does not deal with any JSX business. However, we humans like to see and work with HTML instead of these createElement calls (imagine building a website with just document.createElement, which you can!). This is why the JSX compromise exists. Instead of writing the form above with React.createElement calls, we can write it with a syntax very similar to HTML:

// Example 4 - JSX (compare with Example 3) // //jscomplete.com/repl?j=SJWy3otHW const InputForm = Enter input and click Search ; // InputForm "still" uses the Button component, so we need that too. // Either JSX or normal form would do function Button (props) { // Returns a DOM element here. For example: return {props.label}; } // Then we can use InputForm directly with .render ReactDOM.render(InputForm, mountNode);

Note a few things about the above:

  • It’s not HTML. For example, we’re still doing className instead of class.
  • We’re still considering what looks like HTML above as JavaScript. See how I added a semicolon at the end.

What we wrote above (Example 4) is JSX. Yet, what we took to the browser is the compiled version of it (Example 3). To make that happen, we need to use a pre-processor to convert the JSX version into the React.createElement version.

That is JSX. It’s a compromise that allows us to write our React components in a syntax similar to HTML, which is a pretty good deal.

The word “Flux” in the header above was chosen to rhyme, but it’s also the name of a very popular application architecture popularized by Facebook. The most famous implementation of which is Redux. Flux fits the React reactive pattern perfectly.

JSX, by the way, can be used on its own. It’s not a React-only thing.

Fundamental #3: You can use JavaScript expressions anywhere in JSX

Inside a JSX section, you can use any JavaScript expression within a pair of curly braces.

// To use it:ReactDOM.render(, mountNode);// Example 5 - Using JavaScript expressions in JSX // //jscomplete.com/repl?j=SkNN3oYSW const RandomValue = () => { Math.floor(Math.random() * 100) } ; // To use it: ReactDOM.render(, mountNode);

Any JavaScript expression can go inside those curly braces. This is equivalent to the ${} interpolation syntax in JavaScript template literals.

This is the only constraint inside JSX: only expressions. So, for example, you can’t use a regular if statement, but a ternary expression is ok.

JavaScript variables are also expressions, so when the component receives a list of props (the RandomValue component didn’t, props are optional), you can use these props inside curly braces. We did this in the Button component above (Example 1).

JavaScript objects are also expressions. Sometimes we use a JavaScript object inside curly braces, which makes it look like double curly braces, but it’s really just an object inside curly braces. One use case of that is to pass a CSS style object to the special style attribute in React:

// Example 6 - An object passed to the special React style prop // //jscomplete.com/repl?j=S1Kw2sFHb const ErrorDisplay = ({message}) => {message} ; // Use it: ReactDOM.render( , mountNode );

Note how I destructured only the message out of the props argument. Also note how the style attribute above is a special one (again, it’s not HTML, it’s closer to the DOM API). We use an object as the value of the style attribute. That object defines the styles as if we’re doing so with JavaScript (because we are).

You can even use a React element inside JSX, because that too is an expression. Remember, a React element is essentially a function call:

// Example 7 - Using a React element within {} // //jscomplete.com/repl?j=SkTLpjYr- const MaybeError = ({errorMessage}) => {errorMessage && } ; // The MaybeError component uses the ErrorDisplay component: const ErrorDisplay = ({message}) => {message} ; // Now we can use the MaybeError component: ReactDOM.render(  0.5 ? 'Not good' : ''} />, mountNode );

The MaybeError component above would only display the ErrorDisplay component if there is an errorMessage string passed to it and an empty div. React considers {true}, {false}, {undefined}, and {null} to be valid element children, which do not render anything.

You can also use all of JavaScript functional methods on collections (map, reduce, filter, concat, and so on) inside JSX. Again, because they return expressions:

// Example 8 - Using an array map inside {} // //jscomplete.com/repl?j=SJ29aiYH- const Doubler = ({value=[1, 2, 3]}) => {value.map(e => e * 2)} ; // Use it ReactDOM.render(, mountNode);

Note how I gave the value prop a default value above, because it’s all just Javascript. Note also that I outputted an array expression inside the div. React is okay with that; It will place every doubled value in a text node.

Fundamental #4: You can write React components with JavaScript classes

Simple function components are great for simple needs, but sometimes we need more. React supports creating components through the JavaScript class syntax as well. Here’s the Button component (in Example 1) written with the class syntax:

// Example 9 - Creating components using JavaScript classes // //jscomplete.com/repl?j=ryjk0iKHb class Button extends React.Component { render() { return {this.props.label}; } } // Use it (same syntax) ReactDOM.render(, mountNode);

The class syntax is simple. Define a class that extends React.Component (another top-level React API thing that you need to learn). The class defines a single instance function render(), and that render function returns the virtual DOM element. Every time we use the Button class-based component above (for example, by doing