일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- picker
- 네트워크
- MachineLearning
- Android
- 리눅스
- VirtualBox
- avds
- IOS
- localserver
- centos
- xcode
- 개발
- linux
- TensorFlow
- vsCode
- react
- androidstudio
- unittest
- 맥
- qunit
- build
- jest
- PYTHON
- ReactNative
- Chrome
- node
- 센토스
- webpack
- MAC
- Today
- Total
로메오의 블로그
[DApp - react.js] Election 화면을 React.js로 변경 - back-end 연결 본문
[DApp - react.js] Election 화면을 React.js로 변경 - back-end 연결
romeoh 2019. 7. 8. 06:58App.js에서 truffle과 연결하도록 하겠습니다.
/src/js/App.js
계정 정보를 가져와서 Content.js 콤포넌트로 넘겨서 화면에 표시하도록 하겠습니다.
import React from 'react'
import ReactDOM from 'react-dom'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import Election from '../../build/contracts/Election.json'
import Content from './Content'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// 계정 정보를 저장함
account: '0x0',
}
// web3Provider 생성하기
if (typeof web3 != 'undefined') {
this.web3Provider = web3.currentProvider
} else {
this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545')
}
// web3 생성
this.web3 = new Web3(this.web3Provider)
}
componentDidMount() {
// 계정 정보를 가지고 온다.
this.web3.eth.getCoinbase((err, account) => {
// 계정 정보를 state에 저장함
this.setState({ account })
console.log(account)
})
}
render() {
return (
<React.Fragment>
<h1>투표 결과</h1>
{/* <!-- 로딩바 --> */}
<div id="loader">
<p>로딩중...</p>
</div>
{/* Content compoent를 추가함 */}
<Content
// 계정정보를 Content에 props로 넘겨줌
account={this.state.account}
/>
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
src/js/Content.js
import React from 'react'
import Table from './Table'
import Form from './Form'
export default class Content extends React.Component {
render() {
return (
<div id="content">
{/* <!-- 투표결과 표시 --> */}
<Table />
{/* <!-- 투표하기 --> */}
<Form />
{/* <!-- 계정 정보 표시 --> */}
<p>Your Account: {this.props.account}</p>
</div>
)
}
}
화면에 계정 정보가 표시됩니다.
후보자 목록 가지고 오기
/src/js/App.js
import React from 'react'
import ReactDOM from 'react-dom'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import Election from '../../build/contracts/Election.json'
import Content from './Content'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// 계정 정보를 저장함
account: '0x0',
// 후보자 목록을 저장함
candidates: []
}
// web3Provider 생성하기
if (typeof web3 != 'undefined') {
this.web3Provider = web3.currentProvider
} else {
this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545')
}
// web3 생성
this.web3 = new Web3(this.web3Provider)
// truffle 계약 생성
this.election = TruffleContract(Election)
this.election.setProvider(this.web3Provider)
}
componentDidMount() {
// 계정 정보를 가지고 온다.
this.web3.eth.getCoinbase((err, account) => {
// 계정 정보를 state에 저장함
this.setState({ account })
// 계약 정보를 가지고 온다.
this.election.deployed().then(electionInstance => {
this.electionInstance = electionInstance
// 후보자 Count를 가지고 온다.
this.electionInstance.candidatesCount().then((candidatesCount) => {
for (var i = 1; i <= candidatesCount; i++) {
this.electionInstance.candidates(i).then((candidate) => {
const candidates = [...this.state.candidates]
candidates.push({
id: candidate[0],
name: candidate[1],
voteCount: candidate[2]
});
// 후보자 목록을 저장함
this.setState({ candidates: candidates })
});
}
})
})
})
}
render() {
return (
<React.Fragment>
<h1>투표 결과</h1>
{/* <!-- 로딩바 --> */}
<div id="loader">
<p>로딩중...</p>
</div>
{/* Content compoent를 추가함 */}
<Content
// 계정정보를 Content에 props로 넘겨줌
account={this.state.account}
// 후보자 목록을 Content에 props로 넘겨줌
candidates={this.state.candidates}
/>
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
state에 candidates: [] 를 추가합니다.
"// truffle 계약 생성" 부분에 this.election 객체를 생성하고
"// 계약 정보를 가지고 온다." 부분을 추가해서 candidates에 후보자 목록을 저장합니다.
Content 콤포넌트에 candidates props로 넘겨줍니다.
/src/js/Content.js
import React from 'react'
import Table from './Table'
import Form from './Form'
export default class Content extends React.Component {
render() {
return (
<div id="content">
{/* <!-- 투표결과 표시 --> */}
<Table
candidates={this.props.candidates}
/>
{/* <!-- 투표하기 --> */}
<Form
candidates={this.props.candidates}
/>
{/* <!-- 계정 정보 표시 --> */}
<p>Your Account: {this.props.account}</p>
</div>
)
}
}
props로 받은 candidates 를 Table과 Form에 다시 전달합니다.
/src/js/Table.js
import React from 'react'
export default class Content extends React.Component {
render() {
return (
<React.Fragment>
{/* <!-- 투표결과 표시 --> */}
<table>
<colgroup>
<col width="60" />
<col width="*" />
<col width="100" />
</colgroup>
<thead>
<tr>
<th scope="col">기호</th>
<th scope="col">이름</th>
<th scope="col">득표수</th>
</tr>
</thead>
<tbody id="candidatesResults">
{this.props.candidates.map((candidate, key) => {
return (
<tr key={key}>
<th>{candidate.id.toNumber()}</th>
<td>{candidate.name}</td>
<td>{candidate.voteCount.toNumber()}</td>
</tr>
)
})}
</tbody>
</table>
<hr />
</React.Fragment>
)
}
}
Content.js에서 전달받은 candidates props를 loop 돌려서 table을 완성 합니다.
/src/js/Form.js
import React from 'react'
export default class Content extends React.Component {
render() {
return (
<React.Fragment>
{/* <!-- 투표하기 --> */}
<h2>투표 참여</h2>
<select>
<option value="">후보자를 선택하세요.</option>
{this.props.candidates.map((candidate, key)=> {
return <option value={candidate.id} key={key}>{candidate.name}</option>
})}
</select>
<button>투표하기</button>
<hr />
</React.Fragment>
)
}
}
후보자 목록과 투표 참여 부분에 후보자가 표시됩니다.
로딩중 메세지 처리하기
/src/js/App.js
import React from 'react'
import ReactDOM from 'react-dom'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import Election from '../../build/contracts/Election.json'
import Content from './Content'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
....
// 로딩중 메세지 표시
loading: true,
}
....
}
componentDidMount() {
// 계정 정보를 가지고 온다.
this.web3.eth.getCoinbase((err, account) => {
....
// 계약 정보를 가지고 온다.
this.election.deployed().then(electionInstance => {
....
// 후보자 Count를 가지고 온다.
this.electionInstance.candidatesCount().then((candidatesCount) => {
for (var i = 1; i <= candidatesCount; i++) {
this.electionInstance.candidates(i).then((candidate) => {
....
// 후보자 목록을 저장함
this.setState({
candidates: candidates,
loading: false
})
});
}
})
})
})
}
render() {
return (
<React.Fragment>
....
{ this.state.loading
? <p>로딩중...</p>
: <Content
// 계정정보를 Content에 props로 넘겨줌
account={this.state.account}
// 후보자 목록을 Content에 props로 넘겨줌
candidates={this.state.candidates}
/>
}
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
state에 loading을 추가했습니다.
계약정보를 읽어오면 loading에 false를 넣어줍니다.
render에서 this.state.loading 상태에 따라 로딩중 메세지와 Content를 선별해서 표시해줍니다.
전체 코드는 아래와 같습니다.
import React from 'react'
import ReactDOM from 'react-dom'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import Election from '../../build/contracts/Election.json'
import Content from './Content'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// 계정 정보를 저장함
account: '0x0',
// 후보자 목록을 저장함
candidates: [],
// 로딩중 메세지 표시
loading: true,
}
// web3Provider 생성하기
if (typeof web3 != 'undefined') {
this.web3Provider = web3.currentProvider
} else {
this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545')
}
// web3 생성
this.web3 = new Web3(this.web3Provider)
// truffle 계약 생성
this.election = TruffleContract(Election)
this.election.setProvider(this.web3Provider)
}
componentDidMount() {
// 계정 정보를 가지고 온다.
this.web3.eth.getCoinbase((err, account) => {
// 계정 정보를 state에 저장함
this.setState({ account })
// 계약 정보를 가지고 온다.
this.election.deployed().then(electionInstance => {
this.electionInstance = electionInstance
// 후보자 Count를 가지고 온다.
this.electionInstance.candidatesCount().then((candidatesCount) => {
for (var i = 1; i <= candidatesCount; i++) {
this.electionInstance.candidates(i).then((candidate) => {
const candidates = [...this.state.candidates]
candidates.push({
id: candidate[0],
name: candidate[1],
voteCount: candidate[2]
});
// 후보자 목록을 저장함
this.setState({
candidates: candidates,
loading: false
})
});
}
})
})
})
}
render() {
return (
<React.Fragment>
<h1>투표 결과</h1>
{ this.state.loading
? <p>로딩중...</p>
: <Content
// 계정정보를 Content에 props로 넘겨줌
account={this.state.account}
// 후보자 목록을 Content에 props로 넘겨줌
candidates={this.state.candidates}
/>
}
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
이제 브라우저에서 로딩중 메세지가 사라지고 목록이 표시됩니다.
투표하기
/src/js/App.js
class App extends React.Component {
constructor(props) {
....
// castVote 이벤트를 바인딩 한다.
this.castVote = this.castVote.bind(this)
}
....
// 투표하기
castVote(candidateId) {
this.setState({ loading: true })
this.electionInstance.vote(candidateId, { from: this.state.account })
.then(result => {
this.setState({ loading: false })
})
}
render() {
return (
<React.Fragment>
<h1>투표 결과</h1>
{ this.state.loading
? <p>로딩중...</p>
: <Content
....
// 투표하지 함수를 props로 넘겨줌
castVote={this.castVote}
/>
}
</React.Fragment>
)
}
}
App.js 파일에 위와 같이 코드를 추가합니다.
전체코드는 아래와 같습니다.
import React from 'react'
import ReactDOM from 'react-dom'
import Web3 from 'web3'
import TruffleContract from 'truffle-contract'
import Election from '../../build/contracts/Election.json'
import Content from './Content'
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
// 계정 정보를 저장함
account: '0x0',
// 후보자 목록을 저장함
candidates: [],
// 로딩중 메세지 표시
loading: true,
}
// web3Provider 생성하기
if (typeof web3 != 'undefined') {
this.web3Provider = web3.currentProvider
} else {
this.web3Provider = new Web3.providers.HttpProvider('http://localhost:7545')
}
// web3 생성
this.web3 = new Web3(this.web3Provider)
// truffle 계약 생성
this.election = TruffleContract(Election)
this.election.setProvider(this.web3Provider)
// castVote 이벤트를 바인딩 한다.
this.castVote = this.castVote.bind(this)
}
componentDidMount() {
// 계정 정보를 가지고 온다.
this.web3.eth.getCoinbase((err, account) => {
// 계정 정보를 state에 저장함
this.setState({ account })
// 계약 정보를 가지고 온다.
this.election.deployed().then(electionInstance => {
this.electionInstance = electionInstance
// 후보자 Count를 가지고 온다.
this.electionInstance.candidatesCount().then((candidatesCount) => {
for (var i = 1; i <= candidatesCount; i++) {
this.electionInstance.candidates(i).then((candidate) => {
const candidates = [...this.state.candidates]
candidates.push({
id: candidate[0],
name: candidate[1],
voteCount: candidate[2]
});
// 후보자 목록을 저장함
this.setState({
candidates: candidates,
loading: false
})
});
}
})
})
})
}
// 투표하기
castVote(candidateId) {
this.setState({ loading: true })
this.electionInstance.vote(candidateId, { from: this.state.account })
.then(result => {
this.setState({ loading: false })
})
}
render() {
return (
<React.Fragment>
<h1>투표 결과</h1>
{ this.state.loading
? <p>로딩중...</p>
: <Content
// 계정정보를 Content에 props로 넘겨줌
account={this.state.account}
// 후보자 목록을 Content에 props로 넘겨줌
candidates={this.state.candidates}
// 투표하지 함수를 props로 넘겨줌
castVote={this.castVote}
/>
}
</React.Fragment>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#root')
)
/src/js/Content.js
import React from 'react'
import Table from './Table'
import Form from './Form'
export default class Content extends React.Component {
render() {
return (
<div id="content">
{/* <!-- 투표결과 표시 --> */}
<Table
candidates={this.props.candidates}
/>
{/* <!-- 투표하기 --> */}
<Form
candidates={this.props.candidates}
castVote={this.props.castVote}
/>
{/* <!-- 계정 정보 표시 --> */}
<p>Your Account: {this.props.account}</p>
</div>
)
}
}
Form 콤포넌트에 castVote props를 넘겨줍니다.
/src/js/Form.js
import React from 'react'
export default class Content extends React.Component {
render() {
return (
<React.Fragment>
{/* <!-- 투표하기 --> */}
<h2>투표 참여</h2>
<select
ref={input => this.candidateId = input}
>
<option value="">후보자를 선택하세요.</option>
{this.props.candidates.map((candidate, key)=> {
return <option value={candidate.id} key={key}>{candidate.name}</option>
})}
</select>
<button
onClick={event => {
event.preventDefault()
this.props.castVote(this.candidateId.value)
}}
>
투표하기
</button>
<hr />
</React.Fragment>
)
}
}
select에 ref를 추가하고 button에 onClick 이벤트를 추가해서 castVote 함수를 호출합니다.
투표하기
$ truffle migrate --reset
로컬 블록체인을 reset 해줍니다.
투표하기 하면 MetaMask에서 결제를 승인하고 투표가 완료 됩니다.
브라우저를 새로고침 하면 투표결과가 반영된 것을 확인 할 수 있습니다.
'Backend > Python & Blockchain' 카테고리의 다른 글
[Facial Recognition] 얼굴 비교하기 (0) | 2019.07.19 |
---|---|
[Facial Recognition] 단체사진에서 인원수 알아내기 (0) | 2019.07.19 |
[DApp - react.js] Election 화면을 React.js로 변경 - Component 나누기 (0) | 2019.07.08 |
[DApp - react.js] Election 화면을 React.js로 변경하기 - 환경설정 (0) | 2019.07.08 |
[DApp] Watch Event Listener (2) | 2019.07.08 |