라이플 사이크 메서드는 클래스형 컴포넌트에서만 사용할 수 있음. 함수형 컴포넌트에서는 사용할 수 없음. 대신 Hooks 기능을 사용하여 비슷한 작업을 처리.

7.1 라이프사이클 메서드의 이해

Will 접두사가 붙은 메서드  : 작업을 처리하기 전에 실행되는 메서드
Did 접두사가 붙은 메서드 : 작업을 작동한 후에 실행되는 메서드

종류 : 마운트, 업데이트, 언마운트

마운트

  • 호출 : DOM이 생성되고 웹 브라우저상에 나타날 때
  • 순서 :
    1. constructor :  컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드
    2. getDerivedStateFromProps  : props에 있는 값을 state에 넣을 때 사용하는 메서드
    3. render : 준비한 UI를 렌더링하는 메서드
    4. componentDidMount : 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드

업데이트

  • 호출
    1. props가 바뀔 때
    2. state가 바뀔 때
    3. 부모 컴포넌트가 리렌더링될 때
    4. this.forceUpdate로 강제로 렌더링을 트리거할 때
  • 순서
    1. getDerivedStateFromProps
    2. shouldComponentUpdate : 컴포넌트가 리랜더링을 할지를 결정하는 메서드 (true -> render호출, false -> 여기서 작업 취소)
    3. render
    4. getSnapshotBeforeUpdate : 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출
    5. componentDidUpdate : 컴포넌트의 업데이트 작업이 끝난 후 호출하는 메서드

언마운트 

  • 호출
    • 컴포넌트를 DOM에서 제거할 때
  • 순서
    • componentWillUnmount : 컴포넌트가 웹 브라우저상에서 사라지기 전에 호출

7.2 라이프사이클 메서드 살펴보기

7.3 라이프사클 메서드 사용하기

 

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

9장 컴포넌트 스타일링  (0) 2020.05.24
8장 Hooks  (0) 2020.05.23
6장 컴포넌트 반복  (0) 2020.05.23
5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22

6.1 자바스크립트 배열의 map() 함수

arr.map(callback, [thisArg])

  • callback : 새로운 배열의 요소를 생성하는 함수
    • currentValue : 현재 처리하고 있는 요소
    • index : 현재 처리하고 있는 요소의 index 값
    • array : 현재 처리하고 있는 원본 배열
//map변환 예시
var numbers = [1, 2, 3, 4, 5];
var processed = numbers.map(function (num) {
	return num * num;
});
console.log(processed);

//ES6
var numbers = [1, 2, 3, 4, 5];
var processed = numbers.map(num => num * num);
console.log(processed);
        
        

6.2 데이터 배열을 컴포넌트 배열로 변환하기, 6.3 key

고유한 값이 없을 때 index값을 key로 사용해야 함. 그러나, 이 경우 배열이 변경될 때 효율적으로 리렌더링 하지 못 함.

//key값을 설정해주지 않으면 콘솔에 에러 표시됨. Virtual DOM을 비교하는 과정에서 key로 변화를 빠르게 감지
import React from "react";

const IterationSample = () => {
    const names = ['김', '이', '박', '최'];
    const nameList = names.map((name, index) => <li key={index}>{name}</li>);
    return <ul>{nameList}</ul>;
}

export default IterationSample;

6.4 응용

  • 상태 안에서 배열을 변형할 때 배열에 직접 접근하여 수정하는 것이 아니라 concat, filter 등의 배열 내장 함수를 사용하여 새로운 배열을 만든 후 이를 새로운 상태로 설정해 주어야 한다.

    • 배열 추가 시 push <-> concat : 불변성 X <-> O

    • 배열 변경 시 pop <-> filter : 불변성 X <-> O

import React, {useState} from "react";

const IterationSample = () => {
    const [names, setNames] = useState([
        {id: 1, text: '김'},
        {id: 2, text: '이'},
        {id: 3, text: '박'},
        {id: 4, text: '최'},
    ]);
    const [inputText, setInputText] = useState('');
    const [nextId, setNextId] = useState(5);

    const onChange = e => setInputText(e.target.value);
    const onClick = () => {
        const nextNames = names.concat({
            id: nextId,
            text: inputText
        })
        setNextId(nextId + 1);
        setNames(nextNames);
        setInputText('');
    };
    const onRemove = id => {
        const nextNames = names.filter(name => name.id !== id);
        setNames(nextNames);
    };

    const nameList = names.map(name => (<li key={name.id} onDoubleClick={() => onRemove(name.id)}>{name.text}</li>));
    return (
        <>
            <input value={inputText} onChange={onChange}/>
            <button onClick={onClick}>추가</button>
            <ul>{nameList}</ul>
        </>
    );
}

export default IterationSample;

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

8장 Hooks  (0) 2020.05.23
7장 컴포넌트의 라이프사이클 메서드  (0) 2020.05.23
5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17

리액트에서 태그를 특정화하는데 id대신 ref를 사용해야함. 같은 컴포넌트를 여러 번 사용할 때 중복id가 가진 DOM이 발생하기 때문

5.1 ref는 어떤 상황에서 사용해야 할까?

  • DOM을 꼭 직접적으로 건드려야 할 때
  • DOM을 꼭 사용해야 하는 상황
    • 특정 input에 포커스 주기
    • 스크롤 박스 조작하기
    • Canvas 요소에 그림 그리기 등

5.2 ref 사용

5.2.1 콜백 함수를 통한 ref 설정

//ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달. 이 콜백 함수는 ref값을 파라미터로 전달받음.  
//함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정. this.input은 input 요소의 DOM을 가리킴.(ref이름 자유 지정)

<input ref={(ref)=>{this.input=ref}}/>

5.2.2 createRef를 통한 ref 설정

리액트에 내장되어 있는 createRef함수를 사용하면 더 적은 코드로 ref를 쉽게 사용할 수 있음. (v16.3부터 도입)

import React, {Component} from "react";

class RefSample extends Component {
    input = React.createRef();

    handleFocus = () => {
        this.input.current.focus();
    }

    render() {
        return (
            <div>
                <input ref={this.input}/>
            </div>
        )
    }
}

export default RefSample;

5.3 컴포넌트에 ref 달기

component에도 ref를 달 수 있음. (DOM과 방법 동일).
내부의 ref(메서드 및 멤버 변수)에도 접근할 수 있게 됨.

  • 스크롤 박스를 아래로 내리는 예시
//App.js
import React, {Component} from 'react';
import ScrollBox from "./ScrollBox";

class App extends Component {
    render() {
        return (
            <div>
                <ScrollBox ref={(ref) => this.scrollBox = ref}/>
                <button onClick={()=>this.scrollBox.scrollToBottom()}>
                    맨 밑으로
                </button>
            </div>
        );
    }
}

export default App;


//ScrollBox.js
import React, {Component} from "react";

class ScrollBox extends Component {
    scrollToBottom = () => {
        const {scrollHeight, clientHeight} = this.box;
        this.box.scrollTop = scrollHeight - clientHeight;
    }

    render() {
        const style = {
            border: '1px solid black',
            height: '300px',
            width: '300px',
            overflow: 'auto',
            position: 'relative'
        }
        const innerStyle = {
            width: '100%',
            height: '500px',
            background: 'linear-gradient(white, black)'
        }
        return (
            <div style={style} ref={(ref) => {
                this.box = ref
            }}>
                <div style={innerStyle}/>
            </div>
        );
    }
}

export default ScrollBox;

 

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

7장 컴포넌트의 라이프사이클 메서드  (0) 2020.05.23
6장 컴포넌트 반복  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16

4.1 리액트의 이벤트 시스템

4.1.1 이벤트를 사용할 때 주의 사항

  • 이벤트 이름은 카멜 표기법으로 작성
  • 이벤트에 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달. 
  • DOM 요소에만 이벤트를 설정할 수 있음. (직접 만든 컴포넌트에는 이벤트를 설정할 수 없음.)

4.1.2. 이벤트 종류

4.2 예제로 이벤트 핸들링 익히기

4.2.1 컴포넌트 생성 및 불러오기

4.2.2 onChange 이벤트 핸들링하기

import React, {Component} from "react";

class EventPractice extends Component {
    state = {
        message: ''
    }

    render() {
        return (
            <div>
                <h1>이벤트 연습</h1>
                <input type="text" name="message" placeholder="아무거나 입력해 보세요"
                       value={this.state.message}
                       onChange={(e) => {
                           this.setState({message: e.target.value})
                       }}/>
                <button onClick={() => {
                    alert(this.state.message);
                    this.setState({
                        message: ''
                    });
                }}>확인</button>
            </div>
        );
    }

}

export default EventPractice;

4.2.3 임의 메서드 만들기

//함수 주입
//함수가 호출될 때 this는 호출부에 따라 결정되므로, 클래스의 임의 메서드가 특정 html요소의 이벤트로 등록되는 과정에서
//메서드와 this의 관계가 끊어져 버림.
import React, {Component} from "react";

class EventPractice extends Component {
    state = {
        message: ''
    }

    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

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

    handleClick() {
        alert(this.state.message);
        this.setState({
            message: ''
        });
    }

    render() {
        return (
            <div>
                <h1>이벤트 연습</h1>
                <input type="text" name="message" placeholder="아무거나 입력해 보세요"
                       value={this.state.message}
                       onChange={this.handleChange}/>
                <button onClick={this.handleClick}>확인
                </button>
            </div>
        );
    }

}

export default EventPractice;


// 바벨의 transform-class-properties 문법을 사용하여 화살표 함수 형태로 메소드를 정의
import React, {Component} from "react";

class EventPractice extends Component {
    state = {
        message: ''
    }

    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

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

    handleClick() {
        alert(this.state.message);
        this.setState({
            message: ''
        });
    }

    render() {
        return (
            <div>
                <h1>이벤트 연습</h1>
                <input type="text" name="message" placeholder="아무거나 입력해 보세요"
                       value={this.state.message}
                       onChange={this.handleChange}/>
                <button onClick={this.handleClick}>확인
                </button>
            </div>
        );
    }

}

export default EventPractice;

4.2.4 이벤트 여러개 다루기

    handleChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value
        });
    }

4.2.5 onKeyPress 이벤트 핸들링

4.3 함수형 컴포넌트로 구현해 보기

import React, {useState} from "react";

const EventPractice = () => {
    const [form, setForm] = useState({username: '', message: ''})
    const {username, message} = form;

    const onChange = e => {
        const nextForm = {
            ...form,
            [e.target.name]: e.target.value
        }
        setForm(nextForm);
    }

    const onClick = () => {
        alert(username + ':' + message);
        setForm({
            username: '',
            message: ''
        })
    }

    const onKeyPress = e => {
        if (e.key === 'Enter') {
            onClick();
        }
    }

    return (
        <div>
            <h1>이벤트 연습</h1>
            <input type="text" name="username" placeholder="사용자명" value={username}
                   onChange={onChange}/>
            <input type="text" name="message" placeholder="아무거나 입력해 보세요"
                   value={message}
                   onChange={onChange}
                   onKeyPress={onKeyPress}/>
            <button onClick={onClick}>확인
            </button>
        </div>
    );

}

export default EventPractice;

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

6장 컴포넌트 반복  (0) 2020.05.23
5장 ref:DOM에 이름 달기  (0) 2020.05.23
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16
1장 리액트 시작  (0) 2020.05.16

3.1 클래스형 컴포넌트

클래스형 컴포넌트 특징

  • state 기능 및 라이프사이클 기능을 사용할 수 있음
  • 임의 메서드를 정의할 수 있음.
  • render 함수가 꼭 있어야 함. 

함수형 컴포넌트 특징

  • 클래스형 컴포넌트보다 선언하기 편함
  • 메모리 자원을 클래스형 컴포넌트보다 덜 사용함.
  • 빌드 후 배포할 때도 클래스형 컴포넌트와 비교했을 때 결과물의 크기가 더 작음.
  • state 및 라이프사이클 API를, Hooks라는 기능을 통해 간접 구현( v16.8)
  • 리액트 공식 매뉴얼에서 함수형 컴포넌트와 Hooks를 사용하도록 권장.
1.함수형
import React from "react";
import './App.css';

function App() {
  const name = '리액트';
  return <div className="react">{name}</div>
}

export default App;

2.클래스형
import React, {Component} from "react";
import './App.css';

class App extends Component {
  render() {
    const name = 'react';
    return <div className="react">{name}</div>
  }
}

export default App;

3.2 첫 컴포넌트 생성

//화살표 함수로 함수형 컴포넌트 구현
import React from "react";

const MyComponent = () => {
    return <div>화살표형 함수로 컴포넌트 구현</div>;
};

export default MyComponent;

일반 함수 vs 화살표형 함수

  • 화살표형 함수가 일반 함수를 완전히 대체할 수 있을까? (X) 둘의 용도가 다르므로 완전 대체는 불가능함.
    (화살표 함수는 주로 함수를 파라미터로 전달할 때 유용)
  • 함수 안에서 this를 호출했을 때 일반 함수는 자신이 종속된 객체를 가리키며, 화살표 함수는 자신이 종속된 인스턴스를 가리킴.
  • 화살표 함수는 값을 연산하여 바로 반환해야 할 때 사용하면 가독성을 높일 수 있음.
    (따로 { } 를 열어주지 않으면 연산한 값을 그대로 반환) 
    ex> function twice(value) {return value*2};  ===> const triple = (value) => value*3;
1.일반 함수에서의 this
function BlackDog() {
    this.name = '흰둥이';
    return {
        name: '검둥이',
        bark: function () {
            console.log(this.name + ': 멍멍!');
        }
    }
}

const blackDog = new BlackDog();
blackDog.bark(); //검둥이: 멍멍!


2.화살표 함수에서의 this
function WhiteDog() {
    this.name = '흰둥이';
    return {
        name: '검둥이',
        bark: () => {
            console.log(this.name + ': 멍멍!');
        }
    }
}

const whiteDow = new WhiteDog();
whiteDow.bark(); //흰둥이: 멍멍!

3.3 props

3.3.1 JSX 내부에서 props 랜더링

import React from "react";

const MyComponent = props => {
    return <div>안녕하세요, 제 이름은 {props.name} 입니다.</div>;
};

export default MyComponent

3.3.2 컴포넌트를 사용할 때 props값 지정하기

import React from 'react';
import MyComponent from "./MyComponent";

const App = () => {
    return <MyComponent name="React"/>
}

export default App;

3.3.3 props 기본값 설정 : defaultProps

import React from "react";

const MyComponent = props => {
    return <div>안녕하세요, 제 이름은 {props.name} 입니다.</div>;
};

MyComponent.defaultProps = {
    name: '기본 이름'
}

export default MyComponent

3.3.4 태그 사이의 내용을 보여주는 children

1.children 전달
import React from 'react';
import MyComponent from "./MyComponent";

const App = () => {
    return <MyComponent>리액트</MyComponent>
}

export default App;


2.porps로 받은 children 출력
import React from "react";

const MyComponent = props => {
    return (
        <div>
            안녕하세요, 제 이름은 {props.name} 입니다.<br/>
            children 값은 {props.children}
        </div>);
};

MyComponent.defaultProps = {
    name: '기본 이름'
}

export default MyComponent

3.3.5 비구조화 할당 문법을 통해 props 내부 값 추출하기

import React from "react";

const MyComponent = props => {
    const {name, children} = props;
    return (
        <div>
            안녕하세요, 제 이름은 {name} 입니다.<br/>
            children 값은 {children}
        </div>);
};


export default MyComponent

3.3.6 propTypes를 통한 props 검증

컴포넌트에서 설정한 props가 propsTypes에서 지정한 형태와 일치하지 않는다면 브라우저 개발자 도구의 console 탭에 경고 메시지 출력됨.

import React from "react";
import PropTypes from 'prop-types';

const MyComponent = props => {
...
};

MyComponent.propTypes = {
    name : PropTypes.string,
    favoriteNumber : PropTypes.number.isRequired
}

export default MyComponent

3.3.7 클래스형 컴포넌트에서 props 사용하기

Class형 컴포넌트는 render함수 내부에서 this.props를 조회. defaultProps, propTypes는 함수형 컴포넌트와 같은 방식으로 하거나 class 내부에서 지정

import React, {Component} from "react";
import PropTypes from 'prop-types';


class MyComponent extends Component {
    static defaultProps = {
        name: '기본 이름'
    }

    static propTypes = {
        name: PropTypes.string
    }

    render() {
        const {name, favoriteNumber, children} = this.props; //비구조화 할당
        return (
            <div>
                안녕하세요, 제 이름은 {name} 입니다.<br/>
                children 값은 {children}
                <br/>
                제가 좋아하는 숫자는 {favoriteNumber} 입니다.
            </div>
        );
    }
}

export default MyComponent

3.4 state

3.4.1 클래스형 컴포넌트의 state

state를 설정할 때 constructor 메서드(생성자)를 사용함.
constructor를 작성할 때는 반드시 super(props)를 호출해야 함.
(클래스형 컴포넌트가 상속하고 있는 리액트의 Component 클래스가 지닌 생성자 함수를 호출해줌.)

1.
import React, {Component} from "react";

class Counter extends Component {
    constructor(props) {
        super(props);
        //state의 초깃값 설정하기
        this.state = {
            number: 0,
            fixedNumber: 0
        };
    }

    render() {
        const {number, fixedNumber} = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값  : {fixedNumber}</h2>
                <button onClick={() => {
                    this.setState({number: number + 1});
                    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
                }}>
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;


2.constructor 메소드를 선언하지 않고, state초깃값 설정
import React, {Component} from "react";

class Counter extends Component {
    state = {
        number: 0,
        fixedNumber: 0
    };

    render() {
        const {number, fixedNumber} = this.state;
        return (
            <div>
                <h1>{number}</h1>
                <h2>바뀌지 않는 값 : {fixedNumber}</h2>
                <button onClick={() => {
                    this.setState({number: number + 1});
                    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
                }}>
                    +1
                </button>
            </div>
        );
    }
}

export default Counter;


3.this.setState에 객체 대신 함수 인자 전달

<button onClick={() => {
    this.setState(prevState => {
        return {number: prevState.number + 1}
    });
    // { } 생략해서 함수에서 값 바로 반환
    this.setState(prevState => ({number: prevState.number + 1}));
}}>
    +1
</button>

4.this.setState가 끝난 후 특정 작업 실행하기
<button onClick={() => {
    this.setState({number: number + 1}, () => {
        console.log('방금 setState가 호출되었습니다.');
        console.log(this.state);
    });
    //setState함수는 인자로 전달된 객체 안에 들어 있는 값만 바꾸어 줌.
}}>
    +1
</button>

3.4.2 함수형 컴포넌트에서 useState 사용하기

리액트 16.8이후 userState라는 함수를 사용하여 함수형 컴포넌트에서도 statef를 사용할 수 있게됨.
클래스형 컴포넌트에서의 state 초깃값은 객체 형태를 넣어줘야 하지만, useState는 값의 형태가 자유로움.
함수를 호출하면 배열이 반환됨. 첫 번째 원소는 현재 상태, 두 번째 원소는 상태를 바꿔주는 함수(세터).
배열 비구조화 할당을 통해 이름을 자유롭게 정해 줄 수 있음.

import React, {useState} from "react";

const Say = () => {
    const [message, setMessage] = useState('');
    const onClickEnter = () => setMessage('안녕하세요!');
    const onClickLeave = () => setMessage('안녕히 가세요!');
    return (
        <div>
            <button onClick={onClickEnter}>입장</button>
            <button onClick={onClickLeave}>퇴장</button>
            <h1>{message}</h1>
        </div>
    );
}

export default Say;

3.5 state를 사용할 때 주의 사항

  • state값을 바꾸어야 할 때 setState혹은 useState를 통해 전달받은 세터 함수를 사용해야 함.
  • 배열이나 객체는 사본을 만들고 그 사본에 값을 업데이트한 후, 그 사본의 상태를 setState혹은 세터 함수를 통해 업데이트해야 함.
//객체 다루기
const object = {a: 1, b: 2, c: 3};
const newtObject = {...object, b: 2}; //사본을 만들어서 b값만 덮어 쓰기


//배열 다루기
const array = [
    {id: 1, value: true},
    {id: 2, value: true},
    {id: 3, value: true},
];
let nextArray = array.concat({id: 4});
nextArray.filter(item => item.id !== 2);
nextArray.map(item => (item.id === 1) ? {...item, value: false}, item);

 

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
2장 JSX  (0) 2020.05.16
1장 리액트 시작  (0) 2020.05.16
목차  (0) 2020.05.16

2.1 코드 이해하기

create-react-app은 번들러(웹팩, Parcel browserify) 중 웹팩을 사용하는 프로젝트를 생성함.

이로 인해,

- import 구문을 사용해서 모듈 통합이 가능함.

- 최적화 과정에서 파일 분리가 가능함.

- 로더를 통해서 svg, css, 웹폰트, 미디어 파일 등을 불러와서 사용할 수 있음.

- 최신 자바스크립트 파일을 ES5문법으로 변환해줌.

 

2.2 JSX란?

자바스크립트의 확장 문법이며 XML과 유사. 번들링 과정에서 일반 자바스크립트 형태의 코드로 변환됨.

1.번들링 전
function App() {
	return (
    	<div>
        	Hello <b>react</b>
        </div>
    );  
}

2.번들링 후
function App() {
	return React.createElement("div", null, "Hello", React.createElement("b", null, "react")));
}

 

2.3 JSX의 장점

- 보기 쉽고 익숙하다. (html과 유사)

- 활용도가 높다. (html 태그뿐만 아니라, 새로 만드는 컴포넌트도 JSX안에서 작성 가능)

 

2.4 JSX 문법

2.4.1 감싸인 요소

- 부모 요소 하나로 감싸야함. (Virtual DOM에서 컴포넌트 변화를 감지해 낼 때 효율적으로 비교할 수 있도록 하는 컴포넌트 내부는 하나의 DOM트리 구조로 이 류어 져야 한다는 규칙 존재)

1.잘못된 예
import React from 'react';

function App() {
	return (
    	<h1>리액트 안녕!</h1>
        <h2>잘 작동하니?</h2>
	)
}

export default App;

2.올바른 예
import React from 'react';

function App() {
	return (
		<div>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</div>
	)
}

export default App;

3.v16이상 Fragment 사용 가능
import React, {Fragment} from 'react';

function App() {
	return (
		<Fragment>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</Fragment>
	)
}

export default App;

4.Fragment를 아래와 같은 형태로도 사용 가능
import React, {Fragment} from 'react';

function App() {
	return (
		<>
			<h1>리액트 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</>
	)
}

export default App;

 

2.4.2 자바스크립트 표현

JSX 내부에서 자바스크립트 표현식을 사용하려면 {}를 사용

import React from 'react';

function App() {
	const name = '리액트';
	return (
		<>
			<h1>{name} 안녕!</h1>
			<h2>잘 작동하니?</h2>    
		</>
	)
}

export default App;

 

2.4.3 If문 대신 조건부 연산자

JSX 내부의 자바스크립트 표현식에서 if문 사용 불가. 때문에 JSX밖에서 if문을 사용하여 사전에 값을 설정하거나, { }안에 조건부 연산자(삼항 연산자)를 사용

import React, {Fragment} from 'react';

function App() {
    const name = '리액트';
    return (
        <div>
            {name === '리액트' ? (
                <h1>리액트 안녕!</h1>
            ) : (
                <h2>잘 작동하니?</h2>
            )}
        </div>
    )
}

export default App;

2.4.4 AND 연산자(&&)를 사용한 조건부 렌더링

특정 조건을 만족할 때만 내용을 보여줄 때 사용.

1.null을 렌더링
import React from 'react';

function App() {
    const name = '뤼액트';
    return (
        <div>{name === '리액트' ? <h1>리액트 입니다.</h1> : null}</div>
    )
}

export default App;

2.false를 렌더링 하는 경우 null과 마찬가지로 취급(0은 예외적으로 화면에 나타남)
import React from 'react';

function App() {
    const name = '뤼액트';
    return (
        <div>{name === '리액트' && <h1>리액트 입니다.</h1>}</div>
    )
}

export default App;

2.4.5 undefined를 렌더링하지 않기

1.함수에서 undefine만 반환하여 랜더링할 수 없음
import React from 'react';

function App() {
    const name = undefiend;
    return name;
}

export default App;

2.OR연산자를 통한 해결
import React from 'react';

function App() {
    const name = undefiend;
    return name || '값이 undefined 입니다.';
}

export default App;

3.JSX내부에서 undefined 랜더링 가능
import React from 'react';

function App() {
    const name = undefiend;
    return <div>{name}</div>;
}

export default App;

2.4.6 인라인 스타일링

- DOM요소에 스타일을 적용할 때 객체 형태로 넣어 주어야 함. (문자열 x)

- 카멜표기법으로 작성해야 함 (background-color ==> backgroundColor)

1.객체를 선언하여 전달
import React from 'react';

function App() {
    const name = '리액트';
    const style = {
        backgroundColor: 'black',  //background-color => backgroundColor
        color: 'aqua', 
        fontSize: '48px', //font-size => fontSize
        fontWeight: 'bold', //font-weight =>fontWeight
        padding: 16
    }
    return (
        <div style={style}>{name}</div>
    )
}

export default App;

2.inline 형태로 전달 시
import React from 'react';

function App() {
    const name = '리액트';
    return (
        <div style={{
            backgroundColor: 'black',
            color: 'aqua',
            fontSize: '48px',
            fontWeight: 'bold',
            padding: 16
        }}>{name}</div>
    )
}

export default App;

2.4.7 class대신 className

JSX에서는 class가 아닌 className으로 class 지정.

(v16이상부터는 class로 지정하면 className으로 변환시켜 주고 콘솔에 경고 띄움._

import React from 'react';

function App() {
    const name = '리액트';
    return (
        <div className="react">{name}</div>
    )
}

export default App;

2.4.8 꼭 닫아야 하는 태그

태그는 꼭 닫아야 함

ex> <input> (x), <input></input>, <input/> (o)

2.4.9 주석

JSX 내부에서 주석을 작성할 때는 {/* !@#!@#!#  */}와 같은 형식으로 작성

import React, {Fragment} from 'react';

function App() {
    const name = '리액트';
    return (
        <>
            {/*주석은 이렇게 작성합니다*/}
            <div 
                className="react" //시작 태그를 여러 줄로 작성하게 된다면 여기에 가능.
            >
                {name}
            </div>
            // 하지만 이런 주석이나
            /*이런 주석은 페이지에 그대로 나타나게 됨*/
        </>
    )
}

export default App;

2.5 ESLint와 Prettier 적용하기

- ESLint : 문법 검사도구, 잘못된 문법 시 경고 메시지 화면에 보임. (VS Code : 보기 > 문제 (상단 메뉴))

- Prettier : 코드 스타일 자동 정리 도구 (VS Code : f1 -> format document), 루트 디렉터리에 .prettierrc를 작성해서 커스터마이징

- 저장할 때 코드 자동 정리 :  Code(파일) > 기본 설정 > 설정 (상단메뉴) 에서 텍스트 박스에 format on save 검색하여 체크. 

 

2.6 정리

JSX는 HTML과 비슷하지만 완전히 똑같지 않음. 코드로 보면 XML 형식이지만 실제로는 자바스크립트 객체이며, 용도와 문법이 조금씩 차이가 남.

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
1장 리액트 시작  (0) 2020.05.16
목차  (0) 2020.05.16

1.1 왜 리액트인가?

1.1.1 리액트 이해

- 리액트는 오직 V(View)만 신경 쓰는 라이브러리이다.

- 리액트는 초기랜더링을 위해서 render 함수를 제공함. 

-  조화과정 - 리액트가 화면을 변경하는 방식. (변경 전후의 DOM Tree를 비교.)

 

1.2 리액트의 특징

1.2.1 Virtudal DOM

1.2.2 기타 특징

- 리액트는 뷰만 담당함. 다른 기능은 react-router, axios, redux, MobX등의 라이브러리를 사용하여 구현함.

 

1.3 작업 환경 설정

1.3.1 Node.js와 npm

- 설치 : macOS, Ubuntu

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash 

(Node.js 버전 관리를 위해 nvm을 설치)

$ nvm --version

(버전이 나타나지 않으면 추가 설정 필요)

$ nvm install --lts

(Node.js LTS 버전 설치)

 

- 설치 : Windows

https://nodejs.org/ko/download/ 에서 Window Installer를 내려받아 설치

 

1.3.2 yarn

- macOS (Homebrew를 사용하여 yarn을 설치)

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)(Homebrew 설치 참조 :  https://brew.sh/index_ko)

$ brew update

$ brew install yarn 

$ yarn config set prefix ~/.yarn

$ echo 'export PATH="$(yarn global bin):$PATH"' >> ~/.bash_profile

 

1.3.3 에디터 설치

- VS code 설치.

- VS code 확장 프로그램 설치. ESLint, Reactjs Code Snippets(by charalampos karypidis), Prettier-Code formatter

1.3.4 Git 설치

- macOS https://git-scm.com/download/mac

1.3.5 create-react-app으로 프로젝트 생성하기

$ yarn create react-app hello-react

($ npm init react-app <프로젝트 이름>)

$ cd hellow-react

$ yarn start

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16
목차  (0) 2020.05.16

1장 리액트 시작

2장 JSX

3장 컴포넌트

4장 이벤트 핸들링

5장 ref: DOM에 이름 달기

6장 컴포넌트 반복

7장 컴포넌트의 라이프사이클 메서드

8장 Hooks

9장 컴포넌트 스타일링

10장 일정 관리 웹 애플리케이션 만들기

 

11장 컴포넌트 성능 최적화

12장 immer를 사용하여 더 쉽게 불변성 유지하기

13장 리액트 라우터로 SPA 개발하기

14장 외부 API를 연동하여 뉴스 뷰어 만들기

 

15장 Context API

16장 리덕스 라이브러리 이해하기

17장 리덕스를 사용하여 리액트 애플리케이션 상태 관리하기

18장 리덕스 미들웨어를 통한 비동기 작업 관리

19장 코드 스플리팅

 

20장 서버 사이드 렌더링

21장 백엔드 프로그래밍:Node.js의 Koa 프레임워크

22장 mongoose를 이용한 MongoDB 연동 실습

 

23장 JWT를 통한 회원 인증 시스템 구현하기

24장 프런트엔드 프로젝트: 시작 및 회원 인증 구현

25장 프런트엔드 프로젝트: 글쓰기 기능 구현하기

26장 프런트엔드 프로젝트: 포스트 조회 기능 구현하기

27장 프런트엔드 프로젝트: 수정/삭제 기능 구현 및 마무리

28장 그다음은?

'개발 도서 > 리액트를 다루는 기술(개정판)' 카테고리의 다른 글

5장 ref:DOM에 이름 달기  (0) 2020.05.23
4장 이벤트 핸들링  (0) 2020.05.22
3장 컴포넌트  (0) 2020.05.17
2장 JSX  (0) 2020.05.16
1장 리액트 시작  (0) 2020.05.16

1. General configuration

  • 기본적으로 development profile을 사용한다. 

2. Running the Java server

  • 기본 서버주소 :  http://localhost:8080
  • hot reload가 활성화 되어있음.
  • Maven 이용시
    - maven wrapper를 제공하므로 따로 메이븐 설치가 필요없음.
    - ./mvnw(mac, linux),  mvnw(window)로 어플리케이션 실행. 
    (기본 maven task인 spring-boot:run 을 실행한다.)
    - live reload 사용시 ./mvnw -P-webpack를 통해서 webpack task를 제외시킬 수 있다. 
  • Gradle 이용시
    - gradle wrapper를 제공하므로 따로 그레이들 설치가 필요없음.
    - ./gradlew(mac, linux),  gradlew(window)로 어플리케이션 실행. 
    (기본 gradle task인 bootRun을 실행한다.)
    - live reload 사용시 ./gradlew -x webpack를 통해서 webpack task를 제외시킬 수 있다. 

3. Working with Angular/React

  • npm start 또는 yarn start 로 webpack을 실행시킬 수 있다. (pacage.json scripts참조)
  • webpack hot module reload 서버는 http://localhost:9060/ 로 접근. 
    (Java back-end에 접근하기 위한 proxy 주소 http://127.0.0.1:8080/api)
  • BrowserSync task는 http://localhost:9000/ 을 통해 확인. 
    (http://localhost:9060/ (the Webpack “hot module reload” server)를 프록시 서버로 함.) and which will synchronize the 
  • BrowserSync UI는 http://localhost:3001/ 을 통해 확인.
  • Other NPM/Yarn tasks
    - npm run lint : TypeScript 코드 스타일 검사.
    - npm run lint:fix : TypeScript 스타일을 자동 수정.
    - npm run tsc : TypeScript 코드 컴파일
    - npm run test : Jest 단위 테스트 실행
    -
    npm run test:watch : Jest 단위 테스트를 실행, 코드가 변경되면 자동 피드백.
    - npm run e2e : “end to end” 테스트를 실행(Protractor가 설치됐을 시만 작동)

4. Using a database

  • H2 database
    - http://localhost:8080/h2-console를 통해 접속
  • Database updates
    - JPA entity를 수정하면 db스키마를 따로 수정해줘야 한다.
    (DB 변경 내역 관리를 위해 JPA generator가 아닌, liquibase를 이용함.)
    -
    /src/main/resources/config/liquibase/ 폴더에서 liquibase 관련 내용 확인 가능.
  • entity sub-generator를 통한 db업데이트
    - entity sub-generator를 이용하면 change log가 자동 등록됨.
  • liquibase:diff goal를 통한 db업데이트
    1. JPA entity를 수정
    2. Complie application (Java code를 기반으로 task가 작동하므로 반드시 컴파일이 필요)
    3. /mvnw liquibase:diff (또는 ./mvnw compile liquibase:diff (컴파일후))
    (./gradlew liquibaseDiffChangelog -PrunList=diffLog)
    4. src/main/resources/config/liquibase/changelog 의 체인지 로그 확인.
    5. src/main/resources/config/liquibase/master.xml에 추가
  • change log 편집을 통한 업데이트
    1. JPA entity를 수정
    2. src/main/resources/config/liquibase/changelogd에 change log 생성
    (로그 생성일을 yyyyMMddHHmmss_내용 포맷으로 접두어 붙이는게 네이밍 룰)
    3. src/main/resources/config/liquibase/master.xml에 추가

 

참조 : https://www.jhipster.tech/development/

 

Using JHipster in development

Using JHipster in development Please check our video tutorial on creating a new JHipster application! Summary General configuration Running the Java server Working with Angular/React Using a database Internationalization General configuration IDE configura

www.jhipster.tech

 

JHipster에서 컨트롤러를 생성하길 원할 경우

  • jhipster spring-controller <entity-name>
  • Swagger : 개발환경에서 Administration > API 에서 등록된 컨트롤러를 확인할 수 있다.
  • @Secured 어노테이션을 권한 옵션과 함께 클래스 또는 메소드에 붙임으로써 접근 제한을 할 수 있다.

JHipster에서 서비스를 생성하길 원할 경우

  • JHipster spring-service <entity-name>
  • JHipster는 entity 생성시 Service계층을 따로 생성하지 않는 이유는?
    - 기본적인 CRUD를 제공하는데 목적이 있으므로 서비스 계층이 불필요하다고 생각.
    - 서비스 계층이 여러 repository를 동시에 사용하므로, entity 생성기와 개념이 맞지 않다고 생각.
    + AOP(Proxy)를 위한 interface또한 service 계층에서 불필요하다 생각.
  • 컨트롤러 마찬가지로 @Secured어노테이션을 통한 보안 옵션 사용 가능.

 

참조 : 

- https://www.jhipster.tech/creating-a-spring-controller/

- https://www.jhipster.tech/creating-a-spring-service

 

Creating a service

Creating a Spring service Introduction Note: this sub-generator is much simpler than the entity sub-generator that creates full CRUD entities This sub-generator generates a Spring Service bean, which is where your application’s business logic is supposed t

www.jhipster.tech

 

Creating a controller

Creating a Spring controller Introduction Note: this sub-generator is much simpler than the entity sub-generator that creates full CRUD entities This sub-generator generates a Spring MVC REST Controller. It is also able to create REST methods. In order to

www.jhipster.tech

 

+ Recent posts