초기 렌더링
- 컴포넌트 정의
import React from 'react';
- node_modules 디렉터리의 react모듈을 가져와서 사용
jsx 특징
- 보기 쉬움
- 높은 활용도
jsx 규칙
- 부모에 의해 감싸인 요소
- 자바스크립트 표현
- if문 대신 조건부 연산자
- if문 대신 삼항 연산자 사용
- AND연산자(&&)를 사용한 조건부 렌더링
import React from 'react';
function App() {
const name = '리리액액트트';
return <div> {name === '리액트' && <h1>리액트입니다.</h1>}</div>;
}
export default App;
- undefined를 렌더링하지 않기
- 함수에서 undefined만 반환하는 렌더링 상황을 만들면 안 됨.
- undefied일 때, 보여주고 싶은 문구가 있는 경우
import React from 'react';
import './App.css';
function App() {
const name = undefined;
return <div>{name || '리액트'}</div>;
}
export default App;
- 인라인 스타일링
- 리액트에서 DOM요소에 스타일 적용할 때, 카멜 표기법 사용
- ex) barckground-color => backgroundColor
- 리액트에서 DOM요소에 스타일 적용할 때, 카멜 표기법 사용
import React from 'react';
function App() {
const name = '리액트';
const style = {
backgroundColor : 'black',
color : 'aqua',
fontSize : '48px',
fontWeight : 'bold',
padding : 16
};
return <div style = {style}>{name}</div>
}
export default App;
- class대신 className
- CSS클래스를 사용할 때, class가 아닌 className으로 설정
- 꼭 닫아야 하는 태그
- 태그는 무조건 닫아주기!
- HTML에서는 <input>, <br>태그는 굳이 안닫아줘도 됨
- JSX에서는 태그 무조건 닫아주기!
- ex) <input />
- 태그는 무조건 닫아주기!
- 주석
- {/* */}로 작성
const
- 한번 지정하고 나면 변경이 불가능한 상수
- scope : 블록 단위
let
- 동적인 값을 담을 수 있는 변수
- scope : 블록 단위
function myFunction() {
let a = 1;
if(true) {
let a = 2;
console.log(a); //2
}
console.log(a); //1
}
myFunction();
var
- ES6문법에서 사용 X
- scope(해당 값을 사용할 수 있는 코드 영역) : 함수 단위
function myFunction() {
var a = 'hello';
if(true) {
var a = 'bye';
console.log(a); //bye
}
console.log(a); //bye
}
myFunction();
state, props
state
- 자신이 들고있는 값 (쓰기 전용이라고 봐도 무방)
- 컴포넌트 내부에서 변경할 수 있는 값
- MyComponent.js에서 직접 state값 변경 가능
- 클래스형 컴포넌트에서 constructor 작성 시
constructor(props) {
super(props); //반드시 작성
this.state = { //state의 초기값 설정
number : 0
};
}
- state를 constructor에서 꺼내서 초기값 설정
class Counter extends Component {
state = {
number : 0,
number2 : 0
};
render() {
const {number, numver2} = this.state; //state를 조회할 때, this.state로 조회.
}
}
- state 주의사항
- state값 변경 시, setState or useState를 사용
- ex) 배열 or 객체를 업데이트하는 상황
- 배열 or 객체 사본 생성 => 사본 값 업데이트 => 사본 상태를 setState or 세터함수를 통해 업데이트
- ex) 배열 or 객체를 업데이트하는 상황
- state값 변경 시, setState or useState를 사용
//객체 다루기
const object = {a : 1, b : 2, c : 3};
const nextObject = {...object, b : 2}; //사본을 만들어서 b값만 2로 수정
//배열 다루기
const array = [
{id : 1, value : true},
{id : 2, value : true},
{id : 3, value : false}
];
let nextArray = array.concat({id : 4}); //array에 새 항목 추가
nextArray.filter(item => item.id !== 2); //id가 2인 항목 제거
//id가 1인 항목의 value를 false로 설정.
nextArray.map(item => (item.id === 1? {...item, value : false} : item));
props
- 부모 컴포넌트가 자식 컴포넌트한테 전달하는 데이터 (자식 입장에서 읽기 전용)
- 부모 컴포넌트가 변경할 수 있는 값
- ex) App.js에서 MyComponent의 props를 변경 가능
- 예제
import React, { Component } from 'react'; //react라이브러리에서 Components 클래스 로딩.
import TOC from './components/TOC'
import Content1 from './components/Content'
import Subject from './components/Subject'
import './App.css'; //App.js가 로드될 때, App.css도 같이 로드해서 스타일 입힘.
class App extends Component {
//생성자 : state 초기화. (render()이전에 실행 됨)
constructor(props) {
super(props);
//state 초기화.
this.state = {
mode : 'read',
subject: { title: 'WEB', sub: 'World Wid Web!' },
welcome : {title : 'Welcome', desc : 'Hello, React!'},
test: { test1: 'Test1', test2: 'Test2' },
contents: [
{id : 1, title : 'A', desc : 'A is a'},
{id : 2, title : 'B', desc : 'B is b'},
{id : 3, title : 'C', desc : 'C is c'},
],
}
}
render() {
//test
console.log('App render');
var _title, _desc = null;
if(this.state.mode === 'welcome') {
_title = this.state.welcome.title;
_desc = this.state.welcome.desc;
}else if(this.state.mode === 'read') {
_title = this.state.contents[0].title;
_desc = this.state.contents[0].desc;
}
return (
<div className="App">
<h1 style = {{color : 'Tomato'}}>Subject</h1>
<Subject
title = {this.state.subject.title}
sub = {this.state.subject.sub}
onChangePage = { function() {
this.setState({mode : 'welcome'});
}.bind(this)}
>
</Subject>
<hr></hr>
<h1 style = {{color : 'Tomato'}}>Subject</h1>
<Subject
title={this.state.test.test1}
sub={this.state.test.test2}
onChangePage = {function() {
this.setState({
mode : 'welcome'
});
}.bind(this)}
>
</Subject>
<hr></hr>
<h1 style = {{color : 'Tomato'}}>TOC</h1>
{/* <TOC data = {this.state.contents}></TOC> */}
<TOC
onChangePage = {function() {
alert('Wow!');
this.setState({ mode : 'welcome'});
}.bind(this)}
inputContents={this.state.contents}
></TOC>
<hr></hr>
<h1 style = {{color : 'Tomato'}}>Content1</h1>
<Content1 title={_title} desc={_desc}></Content1>
</div>
);
}
}
export default App;
배열 비구조화 할당
const array [ 1, 2];
const [one, two] = array; //one = 1, two = 2
[ ]로 감싸는 코드
- [ ] 로 감싸져있는 레퍼런스가 가리키는 실제 값이 key값으로 업데이트
const name = 'variantKey';
const object = {
[name] : 'value'
};
- 결과값
- { 'variantKey' : 'value' }
배열 렌더링
- 예제
import React from 'react';
function User({user12}) {
return(
<div>
<b>{user12.username}</b><span>({user12.email})</span>
</div>
);
}
function UserList() {
const users = [
{
id : 1,
username : 'jaewoo',
email : 'aaa'
},
{
id : 2,
username : 'minji',
email : 'bbb'
},
{
id : 3,
username : 'dada',
email : 'ccc'
}
];
return(
<div>
{/* UserList안의 users의 맵핑 */}
{/* user파라미터 (UserList안의 users)가 <User user12 = {user} />를 통해 이름과 이메일 출력 */}
{users.map(user12 => (
<User user12 = {user12} />
))}
</div>
);
}
export default UserList;
함수형 컴포넌트로 구현
//함수형 컴포넌트로 구현
import React, {useState} from 'react';
const EventPractice = () => {
const [form, setForm] = useState({
username : '',
message : ''
});
const {username, message} = form;
const onChange = e => {
const nextForm = {
...form, //기존의 form내용을 이 자리에 복사한 뒤
[e.target.name] : e.target.value //타겟의 value값을 타겟의 name값에 저장
};
setForm(nextForm);
};
const onClick = () => {
alert(username + " : " + message);
setForm({
username : '',
message : ''
});
};
const onKeyPress = e => {
if(e.key === 'Enter') {
onClick();
}
};
return(
<div>
<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;
ref
- 정의
- HTML태그의 id와 유사
- 용도
- DOM을 꼭 직접적으로 건드려야 할 때
- state만으로 해결할 수 없는 기능
- 특정 input에 포커스 주기, 스크롤 박스 조작, Canvas 요소에 그림 그리기 등
- state만으로 해결할 수 없는 기능
- DOM을 꼭 직접적으로 건드려야 할 때
- ref 사용하는 방법
- 콜백 함수를 통한 ref 설정
- ex) <input ref = { (ref) => {this.input = ref} } />
- this.input은 input요소의 DOM을 가리킴
- ref
- input 요소에 ref 콜백 함수를 props로 전달
- (ref)
- 콜백함수의 파라미터
- ex) <input ref = { (ref) => {this.input = ref} } />
- createRef 함수를 통한 ref 설정
- 콜백 함수를 통한 ref 설정
- 예제
- 비밀번호 검증
import React, {Component} from 'react';
import './ValidationSample.css';
class PasswordValidation extends Component{
state = {
password : '',
clicked : false,
validated : false
}
handleChange = (e) => {
this.setState({
password : e.target.value
});
}
handleButtonClick = (e) => {
this.setState({
clicked : true,
validated : this.state.password === '0000'
});
this.input.focus();
}
handleKeyPress = (e) => {
if(e.key === 'Enter') {
this.handleButtonClick();
}
}
render() {
return(
<div>
<input
type = 'password'
value = {this.state.password}
onChange = {this.handleChange}
className = {this.state.clicked ? (this.state.validated ? 'success' : 'failure') : ''}
ref = {ref => this.input = ref}
onKeyPress = {this.handleKeyPress}
/>
<button onClick = {this.handleButtonClick}>검증!</button>
</div>
);
}
}
export default PasswordValidation;
useRef로 컴포넌트 안의 변수 만들기
- 용도
- DOM을 선택하는 용도
- 컴포넌트 안에서 조회, 수정할 수 있는 변수 관리
- useRef로 관리하는 변수 : 값이 변경되어도 컴포넌트 리랜더링X (불필요한 리랜더링 줄임)
useCallback
- 정의
- 컴포넌트 리랜더링될 때마다 새로 만들어진 함수를 사용하지 않도록 최적화
- 문법
- useCallback(생성하고 싶은 함수, 배열);
- 해당 배열이 변경되었을 때만, 함수 생성
- useCallback(생성하고 싶은 함수, 배열);
- 예제
import React, {useState, useMemo, useCallback} from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중...');
if(numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState('');
const onChange = useCallback(e => {
setNumber(e.target.value);
}, []); //컴포넌트가 처음 랜더링될 때만 함수 생성.
const onInsert = useCallback(() => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
}, [number, list]); //number 혹은 list가 바뀌었을 때만 함수 생성.
const avg = useMemo( () => getAverage(list), [list] );
return (
<div>
<input value = {number} onChange = {onChange}/>
<button onClick = {onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<il key = {index}>{value}</il>
))}
</ul>
<div>
<b>평균값 : </b>{avg}
</div>
</div>
);
};
export default Average;
useRef
- 함수형 컴포넌트에서 ref를 쉽게 사용할 수 있도록
- 예제
- 등록 버튼 클릭 => 포커스가 인풋 쪽으로
'React' 카테고리의 다른 글
map() 함수 (0) | 2021.01.21 |
---|---|
useReducer (0) | 2021.01.20 |
EventHandling (0) | 2021.01.19 |
Hooks (0) | 2021.01.18 |
파일 쓰임새 (0) | 2021.01.14 |