"JavaScript Basics Before You Learn React" 를 보고 정리한 글입니다!
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
ES6는 객체 지향 언어(java, python)와 비슷한 방법으로 사용되는 class syntax를 도입했다.
class Developer {
constructor(name){
this.name = name;
}
hello(){
return 'Hello World! I am ' + this.name + ' and I am a web developer';
}
}
: class syntax는 새로운 객체를 생성하게 하는 identifier가 있다.
: constructor method는 항상 object 초기화할 때 호출한다.
: object에 전달된 매개 변수는 새 object로 전달된다.
var nathan = new Developer('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a web developer
한 클래스는 다른 클래스의 정의를 확장할 수 있다. 그리고 해당 클래스에서 초기화된 새 object는 두 클래스들의 모든 메소드를 가진다.
class ReactDeveloper extends Developer {
installReact(){ // ReactDeveloper에 정의된 method
return 'installing React .. Done.';
}
}
var nathan = new ReactDeveloper('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a web developer
nathan.installReact(); // installing React .. Done.
class ReactDeveloper extends Developer {
installReact(){
return 'installing React .. Done.';
}
hello(){ // override 된 메소드
return 'Hello World! I am ' + this.name + ' and I am a REACT developer';
}
}
var nathan = new ReactDeveloper('Nathan');
nathan.hello(); // Hello World! I am Nathan and I am a REACT developer
위의 예시는 자식 클래슥 부모 클래스의 hello 함수를 재정의(override)한 것
import React, { Component } from 'react';
class App extends Component {
// class content
render(){
return (
<h1>Hello React!</h1>
)
}
}
const name = "David";
let age = 28;
var occupation = "Software Engineer";
import React, { Component } from 'react';
class App extends Component {
// class content
render(){
const greeting = 'Welcome to React'; // 전체 application lifecycle에서 변화가 없으므로 const를 사용한다.
return (
<h1>{greeting}</h1>
)
}
}
// regular function
const testFunction = function() {
// content..
}
// arrow function
const testFunction = () => {
// content..
}
const testFunction = (firstName, lastName) => { // 매개변수가 2개 인 경우
return firstName+' '+lastName;
}
const singleParam = firstName => { // 매개변수 1개인 경우 괄호 생략
return firstName;
}
만약 arrow function이 오직 한 줄이라면 return keyword와 중괄호({})를 사용하지 않고 값을 return 할 수 있다.
const testFunction = () => 'hello there.'; // 이렇게 한 줄이다!
testFunction();
arrow function을 이용해서 React Component를 생성할 수 있다.
const HelloWorld = (props) => {
return <h1>{props.hello}</h1>;
}
위의 코드를 ES6 class component로 바꾸면 다음과 같다.
class HelloWorld extends Component {
render() {
return (
<h1>{props.hello}</h1>;
);
}
}
: 확실히 arrow function을 사용하는 것이 React application을 더 간결하게 만들어준다.
: 하지만 component에서 state 사용이 제거됨.
: 이러한 component의 type을 stateless functional component라고 한다.
오직 뷰를 렌더링할 수 있는 컴포넌트, 속성을 전달받아(입력) UI 엘리먼트를 출력하는 기능만 한다.
class HelloWorld extends React.Component {
render() {
return <h1 {…this.props}>Hello {this.props.frameworkName} world!!!</h1>
}
}
const developer = {
firstName: 'Nathan',
lastName: 'Sebhastian',
developer: true,
age: 25,
}
//destructure developer object
const { firstName, lastName } = developer;
console.log(firstName); // returns 'Nathan'
console.log(lastName); // returns 'Sebhastian'
console.log(developer); // returns the object
위의 코드를 볼 수 있듯 developer object의 fisrtName과 lastName을 새로운 변수 firstNAme과 lastName에 할당했다.
만약 firstName을 name이라고 불리는 변수에 저장하고 싶다면..
const { firstName:name } = developer;
console.log(name); // returns 'Nathan'
Destructuring은 또한 배열에서도 작동한다. 이때 object key 대신 index를 사용
const numbers = [1,2,3,4,5];
const [one, two] = numbers; // one = 1, two = 2 즉 one, two는 0번째, 1번째 index의 값을 할당
Destructuring에서 일부 index를 skip하고 싶다면 ,와 함께 전달한다.
const [one, two, , four] = numbers; // one = 1, two = 2, four = 4
대부분 method의 state 가 비구조화에 사용된다. 아래 예시를 보자.
reactFunction = () => {
const { name, email } = this.state;
};
혹은 functional stateless component에서 고려해보자
/*일반적인 functional stateless component*/
const HelloWorld = (props) => {
return <h1>{props.hello}</h1>;
}
우리는 파라미터를 즉시 간단히 비구조화할 수 있다.
const HelloWorld = ({ hello }) => {
return <h1>{hello}</h1>;
}
Destructuring array는 또한 React의 useState hook을 사용한다.
const [user, setUser] = useState('');
Javascript의 array map과 filter 메소드는 React application을 구축할 때 가장 많이 사용되는 ES5 feature 중 하나다. 특히 데이터 processing(처리)에 관해서 많이 사용된다.
이 두 메소드는 데이터 처리에 매우 많이 사용된다. 예를 들어 JSON data의 배열을 리턴하는 API를 상상해보자
const users = [
{ name: 'Nathan', age: 25 },
{ name: 'Jack', age: 30 },
{ name: 'Joe', age: 28 },
];
React의 item의 리스트를 render할 수 있다.
import React, { Component } from 'react';
class App extends Component {
// class content
render(){
const users = [
{ name: 'Nathan', age: 25 },
{ name: 'Jack', age: 30 },
{ name: 'Joe', age: 28 },
];
return (
<ul>
{users
.map(user => <li>{user.name}</li>)
}
</ul>
)
}
또한 render에서 data를 필터링 할 수 있다.
<ul>
{users
.filter(user => user.age > 26)
.map(user => <li>{user.name}</li>)
}
</ul>
ES6 module system은 Javascript가 파일을 import하고 export하게 만들었다. 한번 src/app.js 코드를 다시 보자.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default App;
첫 번째 줄 코드를 보면 import statement를 볼 수 있고
import React, { Component } from 'react';
마지막 줄 코드를 보면 export default statement를 볼 수 있다.
export default App;
이 statement들을 이해하려면 modules syntax에 대해 알아봐야 한다.
module은 exports keyword를 통해 하나 혹은 하나 이상의 값(objects, functions, variables)를 export하는 간단한 JavaScript 파일이다.
먼저 src 디렉토리 안에 util.js라는 이름의 새로운 파일을 생성한다. 그리고 해당 파일에 함수(혹은 객체, 변수)를 작성한다.
touch util.js
이것은 default export다
export default function times(x) {
return x * x;
}
혹은 export를 여러 개 생성한 것이다.
export function times(x) {
return x * x;
}
export function plusTwo(number) {
return number + 2;
}
그리고 우리는 src/App.js에 export들을 import 할 수 있다.
import { times, plusTwo } from './util.js';
console.log(times(2));
console.log(plusTwo(3));
module 당 여러 개의 export들을 생성할 수 있으나, default export는 한 개만 생성할 수 있다. 이때 default export는 중괄호와 export하려는 함수 이름을 사용하지 않고도 import 할 수 있다.
// in util.js
export default function times(x) {
return x * x;
}
// in app.js
import k from './util.js';
console.log(k(4)); // returns 16
하지만 export인 것들에 대해서는 반드시 중괄호와 정확한 이름을 이용해서 import 해야 한다. 그 대신에 import는 가명을 사용하여 두 개의 서로 다른 import에 대해 동일한 이름을 갖지 않도록 할 수 있다.
// in util.js
export function times(x) {
return x * x;
}
export function plusTwo(number) {
return number + 2;
}
// in app.js
import { times as multiplication, plusTwo as plus2 } from './util.js';
혹은 alsolute 이름을 import할 수 있다.
import React from 'react';
import는 javaScript가 해당 패키지 이름에 대해 node_module에서 검사하도록 한다. 따라서 local file을 import하는 경우 올바른 경로를 사용해야 한다.
src/App.js 파일과 export된 App component가 렌더링되는 index.js 파일에서 import를 볼 수 있다. (serviceWorker 부분은 일단 무시)
//index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
./App 디렉토리에서 App을 가져오고 .js 확장자가 생략된 방법에 집중해보자. 우리는 자바스크립트 파일을 import할 때만 파일 확장자를 제외할 수 있지만 .css와 같은 다른 파일에는 파일 확장자를 포함해야 한다. 또한 다른 node module인 react-dom을 import할 수 있다. 이를 통해 React component를 HTML element로 렌더링할 수 있다.