카테고리 없음

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

 

Using the Effect Hook – React

A JavaScript library for building user interfaces

ko.reactjs.org