🔗강의자료:웹 게임을 만들며 배우는 리액트
import와 require는 패키지를 불러오는 방법이다.
es2015 = 바벨이 지원하는 것으로 import
export default NumberBaseball; // import NumberBaseball;
디폴트는 한번만 쓸 수 있고
export const hello = 'hello'; //import { hello }
변수명만 안겹치면 많이 쓸 수 있고 한번에 여러개 가져올 수 있음
common js
const React = require('react');
exports.hello = 'hello';
module.exports = NumberBaseball;
exports 되는게 객체나 배열이면 구조분해 가능
{} 이 부분이 구조분해 문법
노드 모듈 시스템에서 module.exports = {hello: 'a'};
exports.hello = 'a'는 같다.
import React, { Component } from 'react';
하나로 묶을 수 있음
중괄호로 된 것은 default로 export한게 아니라 변수나 값같은걸로 export 가능
이렇게 변환 가능
//import React from 'react';
//import Reactdom from 'react-dom';
//import { hot } from 'react-hot-loader/root';
//import NumberBaseball from './NumberBaseball.jsx';
https://www.daleseo.com/js-module-require/
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
이런 오류가 발생해서 수업과 달리 나는 require를 사용해서 틀린 줄 알고 다시 코드를 import로 작성함 (물론 적으면서도 둘 다 되지 않나? 라는 의문은 있었음)
📝NumberBaseball.jsx
import React, { Component } from 'react';
...
export default NumberBaseball;
📝Client.jsx
import React from 'react';
import ReactDom from 'react-dom';
import NumberBaseball from './NumberBaseball');
ReactDom.render(<NumberBaseball />, document.querySelector('#root'));
로 고치니까 됨. 보니까 require에서도 <NumberBaseball />
부분에 .jsx파일까지 적었길래 안되던거였음
그래서 require로 바꿔서 해보니까 다시 다른 이슈가 뜸
React.createElement is not a function
이번엔 이런 에러가 뜸👶
value
와 onChange
는 같이 꼭 같이 써야함!
-> defaultValue
로 한번에도 가능
💖반복문 map
: 반복하는 부분을 배열로 만들어서 map
함수로 씀
📝입력
<ul>
{['사과','배','딸기','수박','바나나','귤','포도','감','밤'].map((v) => {
return(
<li>{v}</li>
);
})}
</ul>
🎨결과
간단한 배열이 아니라 태그들이 들어가있는 반복문을 만들어야 한다면
📝입력
<ul>
{[
['사과','맛있다'],
['배','맛없다'],
['딸기','달다'],
['수박','시원하다'],
['바나나','싫다'],
['귤','먹고싶다'],
['포도','귀찮다'],
['감','떫다'],
['밤','좋다']
].map((v) => {
return(
<li><b>{v[0]}</b> - {v[1]}</li>
);
})}
</ul>
🎨결과
<ul>
{[
{fruit:'사과', taste: '맛있다'},
{fruit:'배', taste: '맛없다'},
{fruit:'딸기',taste: '달다'},
{fruit: '수박',taste: '시원하다'},
{fruit: '바나나',taste:'싫다'},
{fruit: '귤',taste: '먹고싶다'},
{fruit: '포도',taste: '귀찮다'},
{fruit: '감',taste: '떫다'},
{fruit: '밤',taste: '좋다'},
{fruit: '사과',taste: '좋다'}
].map((v) => {
return(
<li key={v.fruit + v.taste}><b>{v.fruit}</b> - {v.taste}</li>
);
})}
</ul>
=>게 있고 중괄호대신 소괄호나 생략하면 return없이 return할 수 있음
.map(v,i)라고 하고 i를 내면 i는 배열 순서를 말함.
key에 i를 쓰면 안됨 : key역할이 성능 최적화인데 i를 쓰면 기능을 못함.
👉 리액트에서 key를 보고 판단을 하는데 배열순서가 바뀌면 문제가 발생함.
📝 NumberBaseball.jsx
<ul>
{this.fruits.map((v, i) => {
return(
<Try value={v} index={i} />
);
})}
</ul>
📝 Try.jsx
<li>
<b>{this.props.value.fruit}</b> - {this.props.index.fruit}
<div>컨텐츠</div>
<div>컨텐츠1</div>
<div>컨텐츠2</div>
<div>컨텐츠3</div>
</li>
v,i 를 받아줄 수 없기 때문에 props를 사용해서 try.jsx와 연결시켜줌
<Try key={v.fruit + v.taste} value={v} index={i} />
{/* ... */}
() => {}
대신 () {}
이렇게 쓰면 this
를 못쓰고 error가 나타남 리액트에서 push안됨.
- 리액트가 뭐가 바뀌었는지 확인을 못함
const array2 = [...array,2]
기존 array를 복사하고 2를 저장this 반복되어서 보기싫으면 함수밖에
const {value, tries, answer} = this.state;
비구조화 할당으로 간단하게 할 수 있다.
prevTries
로 props를 사용하다보면 문제가 많이 발생함
NumberBaseball이 부모 Try.jsx가 자녀로 props로 연결되어있음
디버깅하기 좋은 확장 프로그램
🎨결과
배포 모드에서는 소스 코드및 최적화가 되어있음.
성능 개선을 위해 사용
렌더가 되는 상황은 state나 props가 바뀌었을 때임.
예시에서 onClick에 setState를 호출하니까 count가 바뀌든 말든 rendering이 다시 일어남.
- 이때 shouldComponentUpdate를 설정해줘야함.
shouldComponentUpdate(nextProps, nextState, nextContext){
if (this.state.counter !== nextState.counter){
return true;
}
return false;
}
👉렌더링이 다시 일어나지 않음.
const array = this.state.array;
this.state.array.push(1);
this.setState({
array: array,
});
👉 이렇게 array이랑 바꾼 array가 같다고 해버리면
PureComponent가 바뀐걸 파악하지못함
새로운 array를 만들고 싶다면 array: [...this.state.array, 1]
이렇게 해줘야함
👉 렌더링 됨을 확인 가능
가능하면 객체 쓰지말고
NumberBaseball 성능 최적화
자식들이 PureComponent나 memo면 부모 코드에도 맞춰서 해줌.
onInput = (c) => {this.inputRef = c;};
해주거나inputRef;
onInputRef = (c) => {this.inputRef = c;}; //함수만들고
//포커스가 필요한 부분에
this.inputRef.focus();
import React, { useState, memo } from 'react'
const inputRef = useRef(null);
inputRef.current.focus();
추가import React,{Component, createRef }from 'react';
inputRef = createRef();
불러오기ref={this.inputRef }
추가this.inputRef.current.focus();
로 추가📝Try.jsx(hooks)
import React, {PureComponenet, memo, useState} from 'react';
const Try = memo(({tryInfo}) => {
const [result, setResult] = useState(tryInfo.result);
const onClick = () =>{
setResult('1');
};
return(
<li>
<div>{tryInfo.try}</div>
<div>{onClick}</div>
</li>
)
}
📝Try.jsx(class)
import React, {PureComponenet, memo, useState} from 'react';
class Try extends PureComponet {
state = {
result : this.props.result,
try: this.props.try,
};
render() {
const {tryInfo} = this.props;
return (
<li>
<div>{this.props.tryInfo.try}</div>
<div>{this.props.tryInfo.result}</div>
</li>
)
}
}