#はじめに
シンプルなdappを開発中です。(氏名、年齢、趣味を登録し、表示させるアプリケーション)
OSは、Mac。ブラウザはChromeを使用しています。
#問題点
React環境下で、会員登録ボタン、及び閲覧ボタンを押した際にコントラクトがうまく更新されません。Choromeが自動的にリロードされてしまいます。
ボタンを押した際にMetamaskの確認画面が出てきて欲しいです。
#ソースコード
solidity
1pragma solidity ^0.5.0; 2 3contract Resister { 4 // アカウント情報 5 struct Data { 6 string name; //名前 7 uint256 age; // 年齢 8 string hobby; // 趣味 9 } 10 11 address[] public users; // 全ユーザーのアドレスを格納 12 13 mapping(address => Data) public accounts; 14 15 // アカウントを登録する関数 16 function registerAccount( 17 string memory _name, 18 uint256 _age, 19 string memory _hobby 20 ) public returns (bool) { 21 //アカウントが登録されていなければ新規会員登録をする 22 if (!isUserExist(msg.sender)) { 23 users.push(msg.sender); 24 } 25 accounts[msg.sender].name = _name; 26 accounts[msg.sender].age = _age; 27 accounts[msg.sender].hobby = _hobby; 28 return true; 29 } 30 31 // アカウントが登録されているかどうかを確認 32 function isUserExist(address user) public view returns (bool) { 33 for (uint256 i = 0; i < users.length; i++) { 34 if (users[i] == user) { 35 return true; 36 } 37 } 38 return false; 39 } 40 41 // アカウント情報を表示させる 42 function viewAccount(address user) 43 public 44 view 45 returns ( 46 string memory, 47 uint256, 48 string memory 49 ) 50 { 51 string memory _name = accounts[user].name; 52 uint256 _age = accounts[user].age; 53 string memory _hobby = accounts[user].hobby; 54 55 return (_name, _age, _hobby); 56 } 57} 58
react
1import React from "react"; 2import Resister from "./Resister.json"; 3import getWeb3 from "./getWeb3"; 4 5import { Row, Col, Button, Form, Modal } from "react-bootstrap"; 6import "bootstrap/dist/css/bootstrap.min.css"; 7 8import "./App.css"; 9 10class App extends React.Component { 11 constructor(props) { 12 super(props); 13 this.state = { 14 web3: null, 15 accounts: null, 16 contract: null, 17 name: null, 18 age: null, 19 hobby: null, 20 address: "", 21 outputName: null, 22 outputAge: null, 23 outputHobby: null, 24 25 //// 26 lines: [], 27 28 // モーダル 29 show: false, 30 // フォームチェック 31 validated: false, 32 }; 33 } 34 35 // モーダル設定 36 handleClose = async () => { 37 await this.setState({ show: false }); 38 39 // ページリロード 40 document.location.reload(); 41 } 42 43 handleShow = async () => this.setState({ show: true }); 44 45 componentDidMount = async () => { 46 try { 47 const web3 = await getWeb3(); 48 49 const accounts = await web3.eth.getAccounts(); 50 const networkId = await web3.eth.net.getId(); 51 const deployedNetwork = Resister.networks[networkId]; 52 const instance = new web3.eth.Contract( 53 Resister.abi, 54 deployedNetwork && deployedNetwork.address 55 ); 56 57 this.setState({ web3, accounts, contract: instance }); 58 } catch (error) { 59 alert( 60 `Failed to load web3, accounts, or contract. Check console for details.` 61 ); 62 console.error(error); 63 } 64 65 const { accounts, contract } = this.state; 66 console.log(accounts); 67 68 const item = await contract.methods.accounts(accounts[0]).call(); 69 this.state.lines.push({ 70 item 71 }); 72 73 console.log(this.state.lines); 74 }; 75 76 // アカウント情報の登録 77 writeRecord = async () => { 78 const { accounts, contract, name, age, hobby } = this.state; 79 const result = await contract.methods.registerAccount(name, age, hobby).send({ 80 from: accounts[0], 81 }); 82 console.log(result); 83 84 if (result.status === true) { 85 this.handleShow(); 86 } 87 }; 88 89 // アカウント情報の読み込み 90 viewRecord = async () => { 91 const { contract, accounts } = this.state; 92 console.log(contract); 93 94 const result = await contract.methods.viewAccount(accounts[0]).call(); 95 console.log(result); 96 97 const outputName = result[0]; 98 const outputAge = result[1]; 99 const outputHobby = result[2]; 100 this.setState({ outputName, outputAge, outputHobby }); 101 }; 102 103 handleChange = (name) => (event) => { 104 this.setState({ [name]: event.target.value }); 105 }; 106 107 // フォーム最終確認 108 handleSubmit = (event) => { 109 const form = event.currentTarget; 110 if (form.checkValidity() === false) { 111 event.preventDefault(); 112 event.stopPropagation(); 113 } 114 this.setState({ validated: true }); 115 }; 116 117 118 render() { 119 return ( 120 <div className="App"> 121 <Row className="text-left m-5"> 122 <Col md={{ span: 4, offset: 2 }}> 123 <Form className="justify-content-center" 124 noValidate validated={this.state.validated} > 125 126 <Form.Group controlId="validationCustom03"> 127 <Form.Label>Name</Form.Label> 128 <Form.Control 129 type="name" 130 onChange={this.handleChange("name")} 131 placeholder="Enter Name" 132 required /> 133 <Form.Control.Feedback type="invalid"> 134 Please enter name. 135 </Form.Control.Feedback> 136 </Form.Group> 137 138 <Form.Group controlId="validationCustom03"> 139 <Form.Label>Age</Form.Label> 140 <Form.Control 141 type="text" 142 onChange={this.handleChange("age")} 143 placeholder="Enter Age" 144 required /> 145 <Form.Text className="text-muted"> 146 We'll never share your age with anyone else. 147 </Form.Text> 148 <Form.Control.Feedback type="invalid"> 149 Please enter age. 150 </Form.Control.Feedback> 151 </Form.Group> 152 153 <Form.Group controlId="validationCustom03"> 154 <Form.Label>Hobby</Form.Label> 155 <Form.Control 156 type="text" 157 onChange={this.handleChange("hobby")} 158 placeholder="Enter Hobby" 159 required /> 160 <Form.Control.Feedback type="invalid"> 161 Please enter hobby. 162 </Form.Control.Feedback> 163 </Form.Group> 164 165 {/* フォームチェック */} 166 <Form.Group> 167 <Form.Check 168 required 169 label="Agree to terms and conditions" 170 feedback="You must agree before submitting." 171 onChange={this.handleSubmit} 172 /> 173 </Form.Group> 174 175 <Button variant="primary" type="submit" onClick={this.writeRecord}> 176 会員登録 177 </Button> 178 {/* モーダル */} 179 <Modal show={this.state.show} onHide={this.handleClose}> 180 <Modal.Header closeButton> 181 <Modal.Title>Wellcome to BcDiary!!</Modal.Title> 182 </Modal.Header> 183 <Modal.Body>会員登録が完了しました。</Modal.Body> 184 <Modal.Footer> 185 <Button variant="secondary" onClick={this.handleClose}> 186 Close 187 </Button> 188 </Modal.Footer> 189 </Modal> 190 </Form> 191 </Col> 192 193 <Col md={{ span: 4, offset: 0 }} className='ml-5'> 194 <Form className="justify-content-center"> 195 <Form.Group controlId="formBasicEmail"> 196 <Form.Label>検索したいアドレスを入力してください。</Form.Label> 197 <Form.Control onChange={this.handleChange("address")} 198 placeholder="Search" /> 199 </Form.Group> 200 <Button variant="primary" type="submit" onClick={this.viewRecord}> 201 閲覧 202 </Button> 203 </Form> 204 205 <br /> 206 <br /> 207 208 {this.state.outputName ? <p>Name: {this.state.outputName}</p> : <p></p>} 209 {this.state.outputAge ? <p>Age: {this.state.outputAge}</p> : <p></p>} 210 {this.state.outputHobby ? <p>Hobby: {this.state.outputHobby}</p> : <p></p>} 211 212 </Col> 213 </Row> 214 </div > 215 ); 216 } 217} 218 219export default App; 220
#バージョン
Truffle v5.1.37 (core: 5.1.37)
Solidity v0.5.16 (solc-js)
Node v14.2.0
Web3.js v1.2.1
あなたの回答
tips
プレビュー