비즈니스 로직과 프레젠테이션 로직을 분리하기 위한 패턴이다.
리액트는 Component단위로, 이벤트 제어와 스타일링이 자유로운 편이며 정해진 양식이 없다. 좀 더 체계적으로 잡아가기 위한 디자인패턴이라고 생각하면 좋다.
데이터 처리와 데이터 출력을 분리 (logic + presneter)
Contaienr: APIRequest, ExceptionError, setState...
Presenter: Only Props, UI, no logic
import React, {Component} from 'react';
import OneAlbum from './OneAlbum.js';
export default class TopAlbum extends Component{
state = {
currentAlbum:0
}
componentDidMount(){
this._listMusic()
}
_listMusic = async() => {
const albums = await.this._callApi()
await this.setState({
albumList:albums
})
this._callOneAlbum()
}
_callApi = () => {
return fetch('api')
.then(album=>album.json())
.catch(err=>console.log(err))
}
_callOneAlbum = ()=> {
const album = this.state.albumList.albums.album
const axelel = album.map((info, index) => {
// OneAlbum Component
return <OneAlbum artist={info.artist.name} albumName={info.name} image={info.image[2]["#text"]} key={index}/>
})
return axelel
}
render() {
return (
<div className="columns is-mobile">
<div className="column is-full">
<div className="columns is-mobile is-padding">
<div className="column">
<h3 className="is-size-3 has-text-weight-bold is-title">Top Albums</h3>
</div>
<div className="column is-2 is-pulled-right is-pulled-bottom has-text-right">
<a href="#" className="is-size-6 has-text-grey">more</a>
</div>
</div>
<hr className="has-background-grey"/>
<div className="columns is-padding is-touch is-4-touch">
{this.state.albumList ? this._callOneAlbum() : 'Loading...'}
</div>
</div>
</div>
)
}
}
🔽🔽🔽
화면에 보여주는 컴포넌트
import React, { Component } from 'react'
export default class OneAlbum extends Component {
static defaultProps = {
artist: 'Artist',
albumName: 'Album',
image: 'Loading'
}
render() {
return (
<div className="column box">
<a href="#" className="has-text-black-ter is-flex-mobile is-hover-scaleup">
<figure className="image is-inline-block">
<img src={this.props.image} alt={this.props.albumName} />
</figure>
<p>
<span className="title is-size-6 is-size-4-mobile">{this.props.albumName}</span>
<br/>
<span className="subtitle is-size-7 is-size-5-mobile has-text-grey">{this.props.artist}</span>
</p>
</a>
</div>
)
}
}