카테고리 없음
React Function Ajax
meta-tony
2023. 4. 9. 15:46
기존의 Class 방식의 코드를 함수방식으로 수정하는 작업을 진행하였습니다.
함수 방식으로 AJAX를 구현할 때 다음과 같이 주의할 점이 있습니다.
- 함수 방식에서는 렌더 이후에 작업이 진행되어 비동기적으로 실행되는 fetch API를 사용하면 충돌이 발생하여 무한 루프가 발생하게 됩니다. 그러므로 함수 useEffect의 사용과 두번째 인자를 사용하여 clean up 작업을 진행해야 합니다.
- 함수에서 map함수 사용시 렌더가 진행된 후에 수정(Hooks)이 이뤄지기 때문에 원형을 수정할 수 없습니다. 따라서 새로운 배열이나 변수를 선언하여 함수를 진행해야하며 반복이 꼭 필요한 경우 forEach()문을 사용해야 합니다.
기존 클래스 방식의 코드
더보기
import React, {Component} from 'react';
import {Nav, Article, NowLoading} from "./ClassList"
class ClassAJAX extends Component {
state = {
article:{
item:{title:'Welcome', desc:"Hello, React & Ajax"},
isLoading:false
},
list:{
items:[],
isLoading:false
}
}
componentDidMount() {
let newList = Object.assign({}, this.state.list, {isLoading:true});
this.setState({list:newList})
fetch('list.json')
.then(function(result){
return result.json();
})
.then(function(json){
this.setState({list:{
items:json,
isLoading:false
}});
}.bind(this))
}
render(){
let NavTag = null;
if(this.state.list.isLoading){
NavTag = <NowLoading />
}else {
NavTag = <Nav list={this.state.list.items} onClick={function(id){
//list contents AJAX
let newArticle = Object.assign({}, this.state.article, {isLoading:true})
this.setState({article:newArticle})
fetch(id + ".json")
.then(function(result){
return result.json();
})
.then(function(json){
this.setState({
article:{
item:{
title:json.title,
desc:json.desc
},
isLoading:false
}
})
}.bind(this))
}.bind(this)} />
}
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} />
}
return (
<div style={{margin:40, border:"1px solid #aaa", padding:40,paddingTop:10}}>
<h1>React AJAX - Class</h1>
{NavTag}
{ArticleTag}
</div>
)};
}
export default ClassAJAX;
함수를 통한 AJAX 구현
import React, { useState, useEffect } from 'react';
const Nav = (props) => {
const listTag = props.list.map((arr) => (
<li key={arr.id}>
<a
href={arr.id}
data-id={arr.id}
onClick={(e) => {
e.preventDefault();
props.onChangeId(e.target.dataset.id);
}}
>
{arr.title}
</a>
</li>
));
return (
<nav>
<ul>{listTag}</ul>
</nav>
);
};
const Article = props => {
return(
<article>
<h2>{props.title}</h2>
{props.desc}
</article>
)
}
const NowLoading = () => {
return(
<div>Now Loading ...</div>
)
}
const FuncAJAX = () => {
const [contents, setContents] = useState({
item: { title: 'Welcome', desc: 'Hello, React & Ajax' },
isLoading: false,
});
const [list, setList] = useState({
items: [],
isLoading: false,
});
const [nowId, setNowId] = useState()
const onChangeId = (e) => {setNowId(e)}
useEffect(() => {
setList({...list, isLoading:true})
fetch('list.json')
.then((result) => {
return result.json();
})
.then((json) => {
setList({
items: json,
isLoading: false,
});
});
}, []);
console.log(nowId)
useEffect(()=>{
if(nowId){
setContents({...contents, isLoading:true})
fetch(nowId + ".json")
.then((result) => {
return result.json();
})
.then((json) => {
setContents({
item:{
title:json.title,
desc:json.desc
},
isLoading:false
})
})
}
},[nowId])
let ArticleTag = contents.isLoading ? <NowLoading /> : <Article title={contents.item.title} desc={contents.item.desc} />
let listTag = list.isLoading ? <NowLoading /> : <Nav list={list.items} onChangeId={onChangeId} />
return (
<div style={{ margin: 40, border: '1px solid #aaa', padding: 40, paddingTop: 10 }}>
<h1>React AJAX - Hooks</h1>
{listTag}
{ArticleTag}
</div>
);
};
export default FuncAJAX;
https://ko.reactjs.org/docs/hooks-effect.html