Copy // src/redux/actions/photos.js
const setFeed = (feed) => ({
type: SET_FEED,
payload: { feed },
})
export const getFeed = () => (dispatch) => {
// 1. 컨트랙트 메서드(READ) 호출: `getTotalPhotoCount()`
//사진이 없는 경우 빈 배열과 함께 'setFeed' 액션을 호출합니다.
KlaystagramContract.methods.getTotalPhotoCount().call()
.then((totalPhotoCount) => {
if (!totalPhotoCount) return []
const feed = []
for (let i = totalPhotoCount; i > 0; i--) {
// 2. 컨트랙트 메서드(READ) 호출: `getPhoto(id)`
// 사진이 있으면 모두 호출합니다.
const photo = KlaystagramContract.methods.getPhoto(i).call()
feed.push(photo)
}
return Promise.all(feed)
})
.then((feed) => {
// 3. 액션 호출: `setFeed(feed)`
// 사진 데이터(피드)를 리덕스 스토어에 저장합니다.
dispatch(setFeed(feedParser(feed))
})
}
After we successfully fetch photo data (feed) from the Klaystagram contract, we call setFeed(feed)
action. 이 액션은 사진 데이터를 페이로드로 가져와 리덕스 스토어에 저장합니다.
Copy // src/components/Feed.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import moment from 'moment'
import Loading from 'components/Loading'
import PhotoHeader from 'components/PhotoHeader'
import PhotoInfo from 'components/PhotoInfo'
import CopyrightInfo from 'components/CopyrightInfo'
import TransferOwnershipButton from 'components/TransferOwnershipButton'
import { drawImageFromBytes} from 'utils/imageUtils'
import { last } from 'utils/misc'
import * as photoActions from 'redux/actions/photos'
import './Feed.scss'
class Feed extends Component {
constructor(props) {
super(props)
this.state = {
isLoading: !props.feed,
}
}
static getDerivedStateFromProps = (nextProps, prevState) => {
const isUpdatedFeed = (nextProps.feed !== prevState.feed) && (nextProps.feed !== null)
if (isUpdatedFeed) {
return { isLoading: false }
}
return null
}
componentDidMount() {
const { feed, getFeed } = this.props
if (!feed) getFeed()
}
render() {
const { feed, userAddress } = this.props
if (this.state.isLoading) return <Loading />
return (
<div className="Feed">
{feed.length !== 0
? feed.map(({
id,
ownerHistory,
data,
name,
location,
caption,
timestamp,
}) => {
const originalOwner = ownerHistory[0]
const currentOwner = last(ownerHistory)
const imageUrl = drawImageFromBytes(data)
const issueDate = moment(timestamp * 1000).fromNow()
return (
<div className="FeedPhoto" key={id}>
<PhotoHeader
currentOwner={currentOwner}
location={location}
/>
<div className="FeedPhoto__image">
<img src={imageUrl} alt={name} />
</div>
<div className="FeedPhoto__info">
<PhotoInfo
name={name}
issueDate={issueDate}
caption={caption}
/>
<CopyrightInfo
className="FeedPhoto__copyrightInfo"
id={id}
issueDate={issueDate}
originalOwner={originalOwner}
currentOwner={currentOwner}
/>
{
userAddress.toUpperCase() === currentOwner.toUpperCase() && (
<TransferOwnershipButton
className="FeedPhoto__transferOwnership"
id={id}
issueDate={issueDate}
currentOwner={currentOwner}
/>
)
}
</div>
</div>
)
})
: <span className="Feed__empty">No Photo :D</span>
}
</div>
)
}
}
const mapStateToProps = (state) => ({
feed: state.photos.feed,
userAddress: state.auth.address,
})
const mapDispatchToProps = (dispatch) => ({
getFeed: () => dispatch(photoActions.getFeed()),
})
export default connect(mapStateToProps, mapDispatchToProps)(Feed)
At the first time, you can only see the text "No photo :D" because there is no photo data in contract yet.
Let's make a UploadPhoto component to send photo data to contract!