const React = require('react');
import React from 'react';
import React, { Component } from 'react';
export
: 여러 번 사용 가능export default
: 한 번만 사용 가능module.exports = NumberBaseball; // export default와 비슷
export.NumberBaseball = 'NumberBaseball'; // == module.export = NumberBaseball;
// 위가 require, 아래는 import와 같은 문법
export default NumberBaseball; // import NumberBaseball;
export const NumberBaseball = 'NumberBaseball'; // import { NumberBaseball }
💡
value
와onChange
는 짝
👉defaultValue
로 한번에 쓸 수도 있다.<input value={this.state.value} onChange={this.onChangeInput} /> <input defaultValue={this.state.value} />
💡
화살표 함수를 사용하면
- constructor를 사용하지 않아도 된다.
- 가독성이 높아진다.
map
함수로 사용<ul>
{['사과', '바나나', '포도', '귤', '감', '배', '파인애플'].map((v) => {
return (
<li>{v}</li>
);
})}
</ul>
<ul>
{[
{fruit: '사과', taste: '맛있다'},
{fruit: '바나나', taste: '맛없다'},
{fruit: '포도', taste: '떫다'},
{fruit: '귤', taste: '시다'},
{fruit: '감', taste: '달다'}
].map((v) => {
return (
<li key={v.fruit}><b>{v.fruit}</b> - {v.taste}</li>
);
})}
</ul>
i
로 인덱스 값을 가져올 수도 있지만, 성능 문제 때문에 key로 사용하지 않는 것이 좋음 💡 key가 필요한 이유 / 인덱스 key가 별로인 이유
- 리액트에서는
key
값을 기준으로 엘리먼트를 추가, 수정, 삭제- 따로 지정하지 않으면 자동으로 인덱스 값으로
key
가 정해짐- 인덱스를
key
로 사용하다가 배열의 순서가 바뀌면 인덱스도 다시 정해져서 성능 저하
return
도 생략 가능 (중괄호 없이 소괄호나 소괄호 없이 바로 리턴값){[...].map((v, i) =>
<li key={v.fruit}><b>{v.fruit}</b> - {v.taste}</li>
)}
NumberBaseball.jsx
import Try from './Try';
...
{this.fruits.map((v, i) => {
return (
<Try key={v.fruit + v.taste} value={v} index={i} /> <!-- props 전달 -->
);
})}
Try.jsx
import React, { Component } from 'react';
class Try extends Component {
render() {
return (
<li>
<b>{this.props.value.fruit}</b> - {this.props.index}
</li>
);
}
}
export default Try;
{/* 내용 */}
// [...복사할 배열, 새로운 배열 선언]
tries: [...prevState.tries, {try: this.state.value, result: '홈런!'}]
this
를 사용하지 않으면 함수를 클래스 밖에 선언하고 사용 가능[1, 2, 3].map((v) => (v * 2)); // [2, 4, 6]
setTries((prevTries) => [...prevTries, {try: value, result: '홈런!'}]);
setState()
가 호출되기만 하면 렌더링이 다시 일어남shouldComponentUpdate()
를 사용해서 렌더링이 일어나는 경우를 제한shouldComponentUpdate(nextProps, nextState, nextContext){
// 현재값과 변경하려는 값이 다를 경우에만 true 리텅 (렌더링)
if(this.state.counter !== nextState.counter){
return true;
}
return false;
}
shouldComponentUpdate
를 구현해둔 Componentarray: [...this.state.array, 1]);
state에 객체 구조를 쓰지 않는 것이 좋다.
import React, {memo} from 'react';
const Try = memo(({ tryInfo }) => { // 컴포넌트를 memo로 감싸줌
return (
<li>
<div>{tryInfo.try}</div>
<div>{tryInfo.result}</div>
</li>
);
});
export default Try;
❗
가장 아래에 있는 자식에 PureComponent나 memo를 적용해야 하며, 모든 자식에 적용이 된 경우 부모 컴포넌트에도 사용 가능
createRef
를 사용하면 Class, Hooks 상관없이 current로 접근 가능import React, { useState, createRef } from 'react';
const inputRef = createRef();
inputRef.current.focus(); // 접근
<input ref={inputRef} maxLength={4} value={value} onChange={onChangeInput} />
this.inputRef.focus(); // 접근
inputRef;
onInputRef = (c) => {
console.log('포커스');
this.inputRef = c;
}
<input ref={this.onInputRef} maxLength={4} value={value} onChange={onChangeInput} />
❗
render()
안에setState()
를 사용하면 무한반복이 발생하므로 주의!
import React, {memo, useState} from 'react';
const Try = memo(({ tryInfo }) => {
const [result, setResult] = useState(tryInfo.result); // props와 state 연결
const onClick = () => {
setResult('1'); // state 변경
}
return (
<li>
<div>{tryInfo.try}</div>
<div onClick={onClick}>{tryInfo.result}</div>
</li>
);
});