//tips
//smart contract
実装を進める中でブラウザ表示にエラーが出ることがわかる。それは以前のreactでのアプリ作成と違いnext.jsを使用するとサーバーでのレンダリングとなり、web3.jsのwindow変数が理解されないからである。
その代わりにメタマスクをユーザーが使用しなくても、ページをみれるように設計できる。
サーバーとブラウザ上で2度レンダリングされる下記を編集する。
import Web3 from 'web3';
//現在では下記の記述が必要になっている
window.ethereum.request({ method: "eth_requestAccounts" });
const web3 = new Web3(window.ethereum);
export default web3;
これをサーバーでもブラウザでもアクセスできるようにする。
import Web3 from "web3";
let web3;
if (typeof window !== "undefined" && typeof window.ethereum !== "undefined") {
// We are in the browser and metamask is running.
window.ethereum.request({ method: "eth_requestAccounts" });
web3 = new Web3(window.ethereum);
} else {
// We are on the server *OR* the user is not running metamask
//ここで自身のproviderを作成している
const provider = new Web3.providers.HttpProvider(
"https://rinkeby.infura.io/v3/15c1d32581894b88a92d8d9e519e476c'"
);
web3 = new Web3(provider);
}
export default web3;
さらにnext.jsのサーバーを使用することで気をつけなければいけないのはブラウザ表示する内容のcomponentDidMountはそのままでは実行されないので、加工して実行させる必要がある。
CampaignIndex を書いてあるIndex.jsを加工する。
class CampaignIndex extends Component{
static async getInitialProps(){
const campaigns=await factory.methods.getDeployedCampaigns.call();
//factoryインスタンスからgetDeployedCampaignsを呼び出し
return {campaigns};
}
render(){
return<div>Campaigns Index!</div>//{this.props.campaigns[0]}
}
}
ここからはセマンティックUI reactという補助キットを使用することでページのhtmlやcssを構築していく。
npm install --save semantic-ui-react
npm install --save semantic-ui-css
その上で、index.jsを下記のように修正。jsだけなく、cssもきちんと追加することを忘れない。
render(){
return(
<div>
<link
rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/semantic-react-ui/2.2.12/semantic.min.css"
/>
<h3>Open Campaign</h3>
{this.renderCampaigns()}
<Button
content="Create Campaign"
icon="add"
primary
/>
</div>
);
}
この中に複数ページで使いまわせる部品を挿入したい場合にはlayout componentとして別の手段を取る。
新たにconponentsフォルダを作成。
import React from "react";
const Layout = (props) => {
return(
<div>
<h1>Im a header</h1>
{props.children}
<h1>Im a footer</h1>
</div>
);
};
export default Layout;
面白いのが、このようにlayout.jsを作成し、
return(
<Layout>
<div>
・・・
</div>
</Layout>
このように挟むことで、挟んだ部分が {props.children}として認識されること。
さらにヘッダーのmenu部分をコンポーネントとして作り込むために別ファイルを作成する。semantic-ui-reactをベースにメニュー機能を取り入れている。
import React from 'react';
import {Menu, MenuHeader} from 'semantic-ui-react';
const Layout = (props) => {
return(
<Menu>
<Menu.Item>
Crowdcoin
</Menu.Item>
<Menu.Menu position="right">
<Menu.Item>
Campaigns
</Menu.Item>
<Menu.Item>
+
</Menu.Item>
</Menu.Menu>
</Menu>
);
};
export default Layout;
これを先のlayoutにインポートして使用する。
const Layout = (props) => {
return(
<div>
<Header />
{props.children}
</div>
);
シンプルにコンポーネントを格納できた。素晴らしい。
今度は新たな遷移先ページを作成していく。
これはpagesフォルダ内にjsで作成する。
現在はindex.jsとshow.jsのみ。show.jsは削除していく。campaignsフォルダを中に作成し、new.jsを組み込んだ。このように新たなキャンペーンはこちらに追加されるようにする。
New.jsを作成する。
import React,{Comment, Component} from 'react';
class CampaignNew extends Component{
render(){
return <h1>New Campaign!</h1>
}
}
export default CampaignNew;