리액트 생명주기
Mount(컴포넌트 처음 실행됨) -> props, state 저장
-> componentWillMount 메소드 호출됨 (DOM에 render 안 됐으므로 props, state 수정 불가)
-> render로 컴포넌트를 DOM에 부착
-> Mount가 완료된 후 componentDidMount 메소드 호출됨
props update 과정
업데이트 발생 감지
-> componentWillReceiveProps 메소드가 호출
-> shouldComponentUpdate, componentWillUpdate가 차례대로 호출
-> 업데이트가 완료(render)
-> componentDidUpdate
참고:
https://lktprogrammer.tistory.com/130
[React] 리액트 - 컴포넌트 생명 주기 (Component Life Cycle)
안녕하세요. 이번 포스팅에서는 컴포넌트 생명 주기 (Component Life Cycle)과 관련된 함수들에 대해서 알아보도록 하겠습니다. 리액트 컴포넌트에는 라이프사이클(Life Cycle)이 존재합니다. 리액트 앱
lktprogrammer.tistory.com
https://talkwithcode.tistory.com/90?category=1019863
React 생명주기 그리고 React hook
안녕하세요! 오늘은 React 생명주기와 Hook에 대해 알아보겠습니다. React Lifecycle 보통 리액트에서 라이프사이클은 class 컴포넌트 기반의 리액트를 말하고는 합니다. 함수형 컴포넌트는 Hook을 사용
talkwithcode.tistory.com
- 클래스형 컴포넌트
import { Component, useState } from 'react';
import './App.css'; //함수형 컴포넌트
function FunCom(props){
// let funcState=useState(props.initNum); //hook => 배열 형태
// let number=funcState[0]; //속성에서 전달받은 값
// let setNumber=funcState[1]; //함수 (새로 전달할 값)
//console.log('함수 state',funcState); let [number, setNumber] = useState(props.initNum); //number로 처음 보여질 정보 useState 안에 넣어둠
let [date, setDate]=useState(new Date().toString());
return(
<div className='container'>
<h2>함수 컴포넌트</h2>
<input type='button' value='random' onClick={()=>{
setNumber(Math.floor(Math.random()*100)+1);
}}></input>
<input type='button' value='date' onClick={()=>{
setDate(new Date().toString());
}}></input>
<p>숫자 : {number}</p> {/*단순 매개변수*/}
<p>날짜 : {date}</p>
</div>
);
}
let classStyle='color:red'; //클래스형 컴포넌트
class ClaCom extends Component{
constructor(props){
super(props);
this.state={
number: this.props.initNum, //7
date: new Date().toString()
}
} componentWillMount(){
console.log('%cclass => componentWillMount 메소드 실행됨',classStyle); //%c : css 스타일 부여
} componentDidMount(){
console.log('%cclass => componentDidMount 메소드 실행됨',classStyle);
}
shouldComponentUpdate(nextProps, nextState){ //렌더링 최적화 (효율화-> 횟수 줄임) //상태 바뀔때마다 호출됨
console.log('%cclass => shouldComponentUpdate 메소드 실행됨',classStyle);
return true; //렌더링 허락
} componentWillUpdate(){
console.log('%cclass => componentWillUpdate 메소드 실행됨',classStyle);
}
componentDidUpdate(){
console.log('%cclass => componentDidUpdate 메소드 실행됨',classStyle); //%c : css 스타일 부여
} render(){
return(
<div className='container'>
<h2>클래스 컴포넌트</h2>
<input type='button' value='random' onClick={()=>{
this.setState({
number:Math.floor(Math.random()*100)+1
});
}}/>
<input type='button' value='date' onClick={()=>{
this.setState({
date:new Date().toString()
});
}}></input>
<p>숫자 : {this.state.number}</p> {/*클래스의 속성 중 initNum 가져옴*/}
<p>날짜 : {this.state.date}</p>
</div>
);
}
} function App() {
return (
<div className="container">
<h1>함수형 컴포넌트 vs 클래스형 컴포넌트</h1>
<FunCom initNum={7}></FunCom>
<ClaCom initNum={7}></ClaCom>
</div>
);
} export default App;
//
class => componentWillMount 메소드 실행됨
class => ClaCom 컴포넌트가 렌더링됨
class => ClaCom 컴포넌트가 렌더링됨
class => componentDidMount 메소드 실행됨
class => shouldComponentUpdate 메소드 실행됨
class => shouldComponentUpdate 메소드 실행됨
class => componentWillUpdate 메소드 실행됨
class => ClaCom 컴포넌트가 렌더링됨
class => ClaCom 컴포넌트가 렌더링됨
class => componentDidUpdate 메소드 실행됨
https://ko-de-dev-green.tistory.com/m/18
React hooks 리액트 훅 useEffect란?
React hooks 리액트 훅 useEffect란? 오늘은 또 하나의 리액트 훅에 없어서는 안 될 useEffect를 알아보겠습니다. 여느 때와 마찬가지로 전혀 비전문적이고 간단하게 설명하려고 합니다. 목차. useEffect
ko-de-dev-green.tistory.com
- 함수형 컴포넌트(렌더 메소드, 상속 없으므로 hooks 이용)
useState를 통해 상태변수를 선언
useEffect를 통해 변화 감지 (마운트, 업데이트, 삭제)
※UseEffect(수행하려는 작업, 상태 감지할 배열)
useEffect(function) : 마운트
useEffect(function,[]) : 첫 마운트
useEffect(function[, deps]) : 첫 마운트 및 state 값 업데이트
import { Component, useState } from 'react';
import './App.css';
let funcStyle='color:blue';
let funcID=0;
//함수형 컴포넌트
function FunCom(props){
// let funcState=useState(props.initNum); //hook => 배열 형태
// let number=funcState[0]; //속성에서 전달받은 값
// let setNumber=funcState[1]; //함수 (새로 전달할 값)
//console.log('함수 state',funcState); let [number, setNumber] = useState(props.initNum);
let [date, setDate]=useState(new Date().toString());
useEffect(function(){
console.log('%cfunc => componentDidMount& componentDidUpdate'+(++funcID));
document.title=number+' : '+date;
});
console.log('%cfunc => 함수형 컴포넌트 실행됨'+(++funcID),funcStyle);
return(
<div className='container'>
<h2>함수 컴포넌트</h2>
<input type='button' value='random' onClick={()=>{
setNumber(Math.floor(Math.random()*100)+1);
}}></input>
<input type='button' value='date' onClick={()=>{
setDate(new Date().toString());
}}></input>
<p>숫자 : {number}</p> {/*단순 매개변수*/}
<p>날짜 : {date}</p>
</div>
);
}
let classStyle='color:red'; //클래스형 컴포넌트
class ClaCom extends Component{
constructor(props){
super(props);
this.state={
number: this.props.initNum, //7
date: new Date().toString()
}
}
componentWillMount(){ //구버전
console.log('%cclass => componentWillMount 메소드 실행됨',classStyle); //%c : css 스타일 부여
}
componentDidMount(){ //신버전
console.log('%cclass => componentDidMount 메소드 실행됨',classStyle); //%c : css 스타일 부여
}
shouldComponentUpdate(nextProps, nextState){
console.log('%cclass => shouldComponentUpdate 메소드 실행됨',classStyle);
return true; //렌더링 허락
}
componentWillUpdate(){ //구버전
console.log('%cclass => componentWillUpdate 메소드 실행됨',classStyle); //%c : css 스타일 부여
}
componentDidUpdate(){ //신버전
console.log('%cclass => componentDidUpdate 메소드 실행됨',classStyle); //%c : css 스타일 부여
}
render(){
console.log('%cclass => ClaCom 컴포넌트가 렌더링됨',classStyle);
return(
<div className='container'>
<h2>클래스 컴포넌트</h2>
<input type='button' value='random' onClick={()=>{
this.setState({
number:Math.floor(Math.random()*100)+1
});
}}/>
<input type='button' value='date' onClick={()=>{
this.setState({
date:new Date().toString()
});
}}></input>
<p>숫자 : {this.state.number}</p> {/*클래스의 속성 중 initNum 가져옴*/}
<p>날짜 : {this.state.date}</p>
</div>
);
}
} function App() {
return (
<div className="container">
<h1>함수형 컴포넌트 vs 클래스형 컴포넌트</h1>
<FunCom initNum={7}></FunCom>
<ClaCom initNum={7}></ClaCom>
</div>
);
} export default App;
리액트 - AJAX
npx create-react-app-ajax
※ AJAX (Asynchronous Javascript And Xml)
서버에 새로고침없이 요청을 할 수 있게 도와주는 JS 라이브러리
서버는 사용자가 요청을 하면 데이터 갖다줌
import { Component } from 'react';
import './App.css';
class Nav extends Component{
render(){
return(
<nav>
<ul>
<li><a href='1'>HTML</a></li>
<li><a href='2'>CSS</a></li>
<li><a href='3'>JavaScript</a></li>
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>환영합니다</h2>
<p>리액트 AJAX 활용입니다</p>
</article>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<h1>리액트 AJAX</h1>
<Nav></Nav>
<Article></Article>
</div>
);
}
}
export default App;
- json 파일 이용
○list.json
[
{"id":1, "title":"HTML"},
{"id":2, "title":"CSS"},
{"id":3, "title":"JavaScript"}
]
○1.json ( => 이름이 숫자면 id만으로 json파일 쉽게 찾을 수 있음 )
{
"id":"1",
"title":"HTML"
}
○2.json
{
"id":"2",
"title":"CSS",
"desc":"홈페이지 꾸미고 레이아웃 설정"
}
○3.json
{
"id":"3",
"title":"JavaScript",
"desc":"동적인 홈페이지로 만든다"
}
○app
import { Component } from 'react';
import './App.css';
class Nav extends Component{
//json을 Ajax로 갖고오기
componentDidMount(){ //컴포넌트 만들어지기 전 수행
fetch('list.json') //데이터 가져오는 비동기함수 (접근하고자하는 url,[options])
.then((result)=>{return result.json();})
//데이터 전달 받은 후 then 함수 구현 //json 메소드: js 코드로 변환
.then((json)=>{console.log(json);});
}
render(){
return(
<nav>
<ul>
<li><a href='1'>HTML</a></li>
<li><a href='2'>CSS</a></li>
<li><a href='3'>JavaScript</a></li>
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>환영합니다</h2>
<p>리액트 AJAX 활용입니다</p>
</article>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<h1>리액트 AJAX</h1>
<Nav></Nav>
<Article></Article>
</div>
);
}
}
export default App;
//
json 변환할 때 오류 떴는데 public 폴더로 json파일들 옮기니까 바로 해결됐다...!
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
라는 오류였음 휴
- json 파일로 렌더링
import { Component } from 'react';
import './App.css';
class Nav extends Component{
constructor(props){
super(props);
this.state={
list:[]
}
}
//json을 Ajax로 갖고오기
componentDidMount(){
fetch('list.json')
.then((result)=>{
return result.json();
})
.then((json)=>{
console.log(json);
this.setState({
list:json
});
});
}
render(){
console.log('Nav 컴포넌트가 렌더링됨');
let listTag=[];
for (let i=0;i<this.state.list.length;i++){
let lis=this.state.list[i];
listTag.push(<li key={lis.id}>
<a href={lis.id}>{lis.title}</a></li>);
}
return(
<nav>
<ul>
{listTag}
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>환영합니다</h2>
<p>리액트 AJAX 활용입니다</p>
</article>
);
}
}
class App extends Component {
render(){
return (
<div className="App">
<h1>리액트 AJAX</h1>
<Nav></Nav>
<Article></Article>
</div>
);
}
}
export default App;
- json파일로 렌더링 2
import { Component } from 'react';
import './App.css';
class Nav extends Component{
constructor(props){
super(props);
this.state={
list:[]
}
}
//json을 Ajax로 갖고오기
componentDidMount(){
fetch('list.json')
.then((result)=>{
return result.json();
})
.then((json)=>{
console.log(json);
this.setState({
list:json
});
});
}
render(){
console.log('Nav 컴포넌트가 렌더링됨');
let listTag=[];
for (let i=0;i<this.state.list.length;i++){
let lis=this.state.list[i];
listTag.push(<li key={lis.id}>
<a href={lis.id}>{lis.title}</a></li>);
}
return(
<nav>
<ul>
{listTag}
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>{this.props.title}</h2> /
<p>{this.props.desc}</p>
</article>
);
}
}
class App extends Component {
//constructor 축약
state={
article:{title:'환영합니다', desc:'리액트 AJAX 활용'}
}
render(){
return (
<div className="App">
<h1>리액트 AJAX</h1>
<Nav onClick={(id)=>{fetch(id+'.json')
.then((result)=>{return result.json();})
.then((end)=>{
this.setState({
article:{
title:end.title,desc:end.desc
}
});
});}}></Nav>
<Article title={this.state.article.title} desc={this.state.article.desc}></Article>
</div>
);
}
}
export default App;
※ fetch
fetch(데이터주소)
.then(함수(데이터받는매개변수){
return 매개변수.json(); //json->js 파일로 변환
})
.then(함수(매개변수){
매개변수에 js객체 활용
});
- 데이터 종속성 제거
Nav 컴포넌트 내부: 목록 표시, AJAX 기능 있음
-> AJAX 기능 옮겨 데이터 종속성 제거
=> 디커플링(decoupling)
1. Presentational Component
보여주는 역할만 담당하는 컴포넌트 (데이터 종속 X)
2. Container Component
프레젠테이셔널 컴포넌트 둘러싼 데이터, 사용자와 상호작용 처리
- nav, article 컴포넌트를 presentational component로 (nav 내부 코드->app)
import { Component } from 'react';
import './App.css';
class Nav extends Component{
render(){
console.log('Nav 컴포넌트가 렌더링됨');
let listTag=[];
for (let i=0;i<this.props.list.length;i++){
let lis=this.props.list[i];
listTag.push(<li key={lis.id}>
<a href={lis.id} data-id={lis.id}
onClick={(event)=>{
event.preventDefault();
this.props.onClick(event.target.dataset.id);
}}>
{lis.title}</a></li>);
}
return(
<nav>
<ul>
{listTag}
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>{this.props.title}</h2>
<p>{this.props.desc}</p>
</article>
);
}
}
class App extends Component {
//constructor 축약
state={
article:{title:'환영합니다', desc:'리액트 AJAX 활용'},
list:[]
}
//json을 Ajax로 갖고오기
componentDidMount(){
fetch('list.json')
.then((result)=>{
return result.json();
})
.then((json)=>{
console.log(json);
this.setState({
list:json
});
});
}
render(){
return (
<div className="App">
<h1>리액트 AJAX</h1>
<Nav list={this.state.list} onClick={(id)=>{fetch(id+'.json')
.then((result)=>{return result.json();})
.then((end)=>{
this.setState({
article:{
title:end.title,desc:end.desc
}
});
});}}></Nav>
<Article title={this.state.article.title} desc={this.state.article.desc}></Article>
</div>
);
}
}
export default App;
- 로딩 기술
import { Component } from 'react';
import './App.css';
class Nav extends Component{
render(){
console.log('Nav 컴포넌트가 렌더링됨');
let listTag=[];
for (let i=0;i<this.props.list.length;i++){
let lis=this.props.list[i];
listTag.push(<li key={lis.id}>
<a href={lis.id} data-id={lis.id}
onClick={(event)=>{
event.preventDefault();
//console.log(event.target.dataset.id);
this.props.onClick(event.target.dataset.id);
}}>
{lis.title}</a></li>);
}
return(
<nav>
<ul>
{listTag}
</ul>
</nav>
);
}
}
class Article extends Component{
render(){
return(
<article>
<h2>{this.props.title}</h2>
<p>{this.props.desc}</p>
</article>
);
}
}
class NowLoading extends Component{
render(){
return(
<div>
<p>로딩 중..</p>
</div>
);
}
}
class App extends Component {
//constructor 축약
state={
article:{
item:{title:'환영합니다', desc:'리액트 AJAX 활용'},
isLoading:false
},
list:{
items:[],
isLoading:false
}
}
//json을 Ajax로 갖고오기
componentDidMount(){
let newList=Object.assign({},this.state.list,{isLoading:true}); //(target, source1, source2)
this.setState({list:newList});
fetch('list.json')
.then((result)=>{
return result.json();
})
.then((json)=>{
console.log(json);
this.setState({list:
{items:json,
isLoading:false}
}); {/*정보 다 가져왔으니 false로 바꿈*/}
});
}
render(){
//Nav 처리
let NavTag=null;
if(this.state.list.isLoading){
NavTag=<NowLoading></NowLoading>
}else{
NavTag=<Nav list={this.state.list.items}
onClick={(id)=>{
let newArticle=Object.assign({},this.state.article,{isLoading:true});
this.setState({article: newArticle});
fetch(id+'.json')
.then((result)=>{return result.json();})
.then((json)=>{
this.setState({
article:{item: {title:json.title, desc:json.desc}},
isLoading:false
});
});
}}></Nav>
}
//Article 처리
let ArticleTag=null;
if(this.state.article.isLoading){
ArticleTag=<NowLoading></NowLoading>
}else{
ArticleTag=<Article
title={this.state.article.item.title}
desc={this.state.article.item.desc}></Article>
}
return (
<div className="App">
<h1>리액트 AJAX</h1>
{NavTag}
{ArticleTag}
</div>
);
}
}
export default App;
※ Object.assign(target, sources,...)
객체 병합 및 복제 메소드
source 객체들이 target으로 병합돼 return 됨
타겟이 빈 객체({}) => 소스 객체들이 병합된 새로운 객체 반환함
참고:
https://joooing.tistory.com/entry/Objectassign?category=907322
Object.assign()
Object.assign() Object.assign() 메소드는 열거할 수 있는 하나 이상의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용합니다. 대상 객체를 반환합니다. MDN문서에 따르면 Object.assign() 메서드의 정의
joooing.tistory.com
'Programming > 국비학원' 카테고리의 다른 글
220809 - 자바스크립트 - 기초 문법, JSON 표기법 (0) | 2022.08.10 |
---|---|
220808 - 리액트 - redux, es6 (0) | 2022.08.09 |
220804 - 리액트 - 라우터돔 (0) | 2022.08.05 |
220803 - 리액트 - update(기존 목록 내용 변경), delete(선택 목록 삭제) (0) | 2022.08.04 |
2220802 - 리액트 - (Read) 메뉴 클릭 시 내용 표시 / (Create) 생성버튼 클릭 시 목록에 추가 (0) | 2022.08.03 |