2017-11-01 18 views
0

私はローカルtestrpcブロックチェインにsolidityコントラクトを導入しました。私の契約方法のテストはすべてチェックアウトされていますが、Web3のトランザクションを処理して状態を更新することは私に問題をもたらしています。リアクションsetState内部solidityコントラクトインスタンス約束

私はユーザーアカウントを追加するとき、私の次の操作は契約のすべてのユーザーアカウントを返すことです。とよく...私の状態(RegisteredAccounts)を更新します。 しかし、私の約束のチェーンを通じて、私は自分の状態が更新されているのを見ていない。私はsetStateも非同期であることを理解していますので、ページを更新したりComponentDidMount()を呼び出すことなく状態を更新するにはどうしたらいいですか?

ここに私のソリディティアカウント契約(私はこれまでここで

pragma solidity^0.4.4; 
 
contract Accounts { 
 

 
    mapping(address => User) public mUsers; 
 
    address[] public Users; //users whitepages 
 

 
    struct User { 
 
    string handle; 
 
    bytes32[] taskList; 
 
    } 
 

 
    function addNewUser(string _handle) returns(bool success) { 
 
    address newUserAddr = msg.sender; 
 

 
    //if handle not in userAddresses & the handle is not null 
 
    if (bytes(mUsers[newUserAddr].handle).length == 0 && bytes(_handle).length != 0) { 
 
     mUsers[newUserAddr].handle = _handle; 
 
     Users.push(newUserAddr); 
 
     return true; 
 
    } else { 
 
     return false; 
 
    } 
 
    } 
 

 
    function getUsers() constant returns(address[]) { 
 
    return Users; 
 
    } 
 
}

扱わきた部分は私のアプリのコンテナコンポーネントです - 関連部分 は、registerNewUserは()私の問題です現在子供です。

class App extends Component { 
 
    state = { 
 
    modalOpen: false, 
 
    SenderAddress: null, 
 
    RegisteredAccounts: [], 
 
    isRegisteredUser: false, 
 
    SenderTaskList: [], //not set 
 
    AccountsCtrct: null, 
 
    web3: null 
 
    } 
 
    //#region APP METHODS 
 
    componentWillMount() { 
 
    // Get network provider and web3 instance. -- See utils/getWeb3 for more info. 
 
    getWeb3.then(results => { 
 
     this.setState({ 
 
     web3: results.web3 
 
     }) 
 
     this.instantiateContracts() //instantiate contract 
 
    }).catch(() => { 
 
     console.log('Error finding web3.') 
 
    }) 
 
    } 
 

 

 
    instantiateContracts() { 
 
    this.setState({ 
 
     AccountsCtrct: contract(AccountsContract) 
 
    }) 
 
    this.state.AccountsCtrct.setProvider(this.state.web3.currentProvider) 
 

 
    //Get block chain addresses --- only returns the current address selected in metamask (web3 current addr) 
 
    this.state.web3.eth.getAccounts((error, accounts) => { 
 
     this.setState({ 
 
     SenderAddress: accounts[0] 
 
     }) 
 

 
     //INIT ACCOUNTS CONTRACT 
 
     var acctDeployed = this.state.AccountsCtrct.deployed() 
 
     acctDeployed.then((instance) => { 
 
     return instance.getUsers(); 
 
     }).then((res) => { 
 
     this.setState({ 
 
      RegisteredAccounts: res 
 
     }) 
 

 
     if (this.state.RegisteredAccounts.includes(this.state.SenderAddress)) { 
 
      this.setState({ 
 
      isRegisteredUser: true 
 
      }) 
 
     } 
 
     }) 
 
    }) 
 
    } 
 

 

 
    registerUser = (handle) => { 
 
    var acctInstance 
 
    this.state.AccountsCtrct.deployed().then((inst) => { 
 

 
     //add current user to this account 
 
     acctInstance = inst 
 
     return acctInstance.addNewUser(handle, { 
 
     from: this.state.SenderAddress 
 
     }); 
 
    }).then(() => { 
 

 
     //now we added our user -- update registeredAccounts setState 
 
     //pass response users array to promise 
 
     return acctInstance.getUsers() 
 
    }).then(res => { 
 

 
     this.setState({ 
 
     RegisteredAccounts: res 
 
     }) 
 
     if (res.includes(this.state.SenderAddress)) { 
 
     this.setState({ 
 
      isRegisteredUser: true 
 
     }) 
 
     } 
 
    }) 
 
    } 
 

 
    toggleModal =() => { 
 
    this.setState(prevState => ({ 
 
     modalOpen: !prevState.modalOpen 
 
    })); 
 
    } 
 
    //#endregion 
 
    
 
    render() { 
 
    return (
 
     <div className="App"> 
 
     <nav className="navbar pure-menu pure-menu-horizontal"> 
 
      <a href="#" className="pure-menu-heading pure-menu-link">Truffle Box</a> 
 
      { 
 
       !this.state.isRegisteredUser 
 
       ? <a style={navLink} onClick={ this.toggleModal } href="#" className="pure-menu-heading pure-menu-link">Register</a> 
 
       : null 
 
      } 
 
     </nav> 
 

 
     <ModalUserNav visible={this.state.modalOpen} 
 
       toggleModal={this.toggleModal} 
 
       isRegistered={this.state.isRegisteredUser} 
 
       registerUser={this.registerUser} /> 
 
    ); 
 
    } 
 
}

最終私の子コンポーネント要するに

class ModalUserNav extends Component { 
 
    state = { 
 
    unpl: "UserName", 
 
    pwpl: "Password", 
 
    errorCode: 'Registration Failed', 
 
    errorVisible: false 
 
    } 
 

 

 
    handleOnChangePL = (e) => { 
 
    this.setState({ 
 
     [e.target.name]: e.target.value 
 
    }) 
 
    } 
 

 
    handleSubmit =() => { 
 
    if (this.state.unpl !== "") { 
 
     this.props.registerUser(this.state.unpl) 
 
     this.props.toggleModal(); 
 
    } else { 
 
     //if the input is empty update the error code and show 
 
     console.log('registration failed!') 
 
     this.setState({ 
 
     errorCode: 'REGISTRATION ERR: empty handles are not allowed!', 
 
     errorVisible: true 
 
     }) 
 
    } 
 
    } 
 

 
    render() { 
 
    return (
 
     <section> 
 
      <Modal visible={this.props.visible} effect="fadeInUp"> 
 
      <div className="pure-form"> 
 
       <fieldset style={modalFormView}> 
 
       <legend style={{fontSize: "18px"}}><b>Register now. All you need is a handle!</b></legend> 
 
       <div className="flexContainer"> 
 
        <input style={{marginTop: "7px", height: "2.6em", marginLeft: "5px", marginRight: "5px"}} type="text" name="unpl" placeholder={this.state.unpl} onChange={(event) => {this.handleOnChangePL(event)}} value={this.state.unpl} /> 
 
        <button style={btnStyle} type="submit" className="pure-button pure-button-primary" onClick={() => {this.handleSubmit()}}><b>Register</b></button> 
 
       </div> 
 
       </fieldset> 
 
      </div> 
 
      </Modal> 
 
     </section> 
 
    ) 
 
    } 
 
}

、私は自動的にせずに私のUIを変更できるようにSETSTATEと私の2つの非同期タスク(addNewUser、getUsers)をフォローアップしたいですさわやか。だから私は何が間違っているの?私は知っておく必要があります。

ありがとうございます!

答えて

0

setStateはすぐにデータを更新しないため、instantiateContractssetStateに移動する必要があります。 https://reactjs.org/docs/react-component.html#setstate

this.setState({ 
    web3: results.web3 
    },() => { 
    this.instantiateContracts() //instantiate contract 
    }) 

アップデート1:約registerUser:それは

this.setState({ 
    RegisteredAccounts: res 
    },() => { 
    if (res.includes(this.state.SenderAddress)) { 
     this.setState({ 
     isRegisteredUser: true 
     }) 
    } 
    }) 
+0

に注意する必要があります!私はそのビットを変更したヒントありがとう。私のregisterUserメソッドのアドバイスはありますか?終了後にUIを更新することも可能ですか?またはUIを更新するためにキューに入れるデータを更新するsetStateのリスナー? –

+0

@CameronTreyHeilman答えを更新しました – imcvampire