【问题标题】:React JS: Cannot get input from user, get undefined when typingReact JS:无法从用户那里获取输入,输入时未定义
【发布时间】:2017-07-11 16:45:19
【问题描述】:

我正在编写一个应用程序,以便用户填写注册表,然后使用 React JS 显示此人的姓名和其他参数,所有这些也来自智能合约。我在输入文本输入后遇到了未定义输入的问题,我怀疑这与状态有关,但不知道如何解决。

这是父代码的代码,称为 App.js:

import React, { Component } from 'react';
import logo from './logo.svg';
import dxclogo from './dxclogo.png';
import './App.css';
import Web3 from 'web3';
import _ from 'lodash'
import { Form } from './Form';

//Declaring the ethereum client (initializing) with the url in which the testrpc is running
var ETHEREUM_CLIENT = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))

//These could be dynamically added through input fields, but hard coding for now
var peopleContractABI = [{"constant":true,"inputs":[],"name":"getPeople","outputs":[{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"people","outputs":[{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"age","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_age","type":"bytes32"}],"name":"addPerson","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]

var peopleContractAddress = '0x7d58e54b812b1f7c5c47f0a85af5f9f6a1d3f5c8'

var peopleContract = ETHEREUM_CLIENT.eth.contract(peopleContractABI).at(peopleContractAddress)

class App extends Component{
  constructor(props){
    super(props);
    this.state = {
      firstNames: [],
      lastNames: [],
      ages: []
    }
  }

  componentWillMount(){
    var data = peopleContract.getPeople()
    this.setState({
      firstNames: String(data[0]).split(','),
      lastNames: String(data[1]).split(','),
      ages: String(data[2]).split(',')
    })
  }

  render() {
    var TableRows = []

    _.each(this.state.firstNames, (value, index) => {
    TableRows.push(
      <tr>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.firstNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.lastNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.ages[index])}</td>
      </tr>
    )
  })

    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <img src = {dxclogo} className ="App-dxclogo" alt="dxclogo" />
          <h1>Hotel Room Booking dApp</h1>
        </div>
        <div>
          <Form />
          <table className="App-tablePeople">
            <thead>
              <tr>
                <th>First Name </th>
                <th>Last Name </th>
                <th>Age </th>
              </tr>
            </thead>
            <tbody>
              {TableRows}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

export default App;

子代码,称为 Form.js

import React from 'react';
import Web3 from 'web3';

//Declaring the ethereum client (initializing) with the url in which the testrpc is running
var ETHEREUM_CLIENT = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))

//These could be dynamically added through input fields, but hard coding for now
var peopleContractABI = [{"constant":true,"inputs":[],"name":"getPeople","outputs":[{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"people","outputs":[{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"age","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_age","type":"bytes32"}],"name":"addPerson","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]

var peopleContractAddress = '0x7d58e54b812b1f7c5c47f0a85af5f9f6a1d3f5c8'

var peopleContract = ETHEREUM_CLIENT.eth.contract(peopleContractABI).at(peopleContractAddress)

//Need to create a variable named accounts in order to know which account
//to make the transactions from
var accounts = ETHEREUM_CLIENT.eth.accounts

//Creating the dynamic input fields for the user to input his/her data
export class Form extends React.Component{
  constructor(props){
  super(props);
  this.state = {
    firstName: "",
    lastName: "",
    age: "",
  }

  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({firstName: event.target.firstName});
    this.setState({lastName: event.target.lastName});
    this.setState({age: event.target.age});

  }

  handleSubmit(event) {
    alert('A user was submitted: ' + this.state.firstName + this.state.lastName + this.state.age);
    event.preventdefault();
  }


//Creating so that person can be added
  componentWillMount(){
     peopleContract.addPerson(this.state.firstName, this.state.lastName, this.state.age, {from: accounts[1], gas: 3000000})
    }

  render() {
    return(
      <form onSubmit={this.handleSubmit}>
      <h4>Name</h4>
        <input
          type="text"
          placeholder="Name, e.g. Javier"
          firstName={this.state.firstName}
          onChange={this.handleChange}  />
        <div>
        <h4>Last Name</h4>
          <input
            type="text"
            placeholder="Last Name, e.g. Hernandez"
            lastName={this.state.lastName}
            onChange={this.handleChange}/>
        </div>
        <div>
        <h4>Age</h4>
          <input
            type="text"
            placeholder="Age, e.g. 35"
            age={this.state.age}
            onChange={this.handleChange}/>
        </div>
        <input
          type = "submit"
          name = "Submit"
          />
      </form>
    );
  }
}

【问题讨论】:

  • event.target.firstName 应该是什么?我想你的意思是event.target.value
  • firstName 在代码中意味着和value 相同,或者这就是我的想法
  • event.target 指的是没有firstName 属性的DOM 节点。使用event.target.value,您将看到传入的值
  • 您也可以附加您的handleChange 函数来获取额外的参数,即状态键。如果这对你有用,我可以写一个答案
  • 是的,这可行。如果你能写一个解决方案,我将不胜感激

标签: reactjs react-redux ethereum solidity


【解决方案1】:

您在正确的轨道上,但您的 handleChange 函数编码有点太硬了。获取更多参数,使其适用于任何输入:

handleChange(event, key) {
  this.setState({ [key]: event.target.value })
}

更新您的 onChange 处理程序以传递该信息:

<input
  type="text"
  placeholder="Name, e.g. Javier"
  firstName={this.state.firstName}
  onChange={event => this.handleChange(event, 'firstName')}  
/>

对于其余的输入,依此类推。然后您可以提交,您的表单将包含所有必要的状态。如果没有,您可以在那里进行一些验证。

【讨论】:

  • 这现在有效,但我得到的是单个字母,而不是整个单词。我进行了更改,以便在渲染中拥有 peopleContract.addPerson 函数,例如 render() { peopleContract.addPerson(this.state.firstName, this.state.lastName, this.state.age, {from: accounts[1], gas: 3000000}) return(
  • 你从哪里得到单个字母?
  • 你能用最新的代码更新你的问题吗
【解决方案2】:

这是最新的代码。使用

在本地主机网络中输出文本时,我收到了单个字母
componentWillMount(){
    var data = peopleContract.getPeople()
    this.setState({
      firstNames: String(data[0]).split(','),
      lastNames: String(data[1]).split(','),
      ages: String(data[2]).split(',')
    })
  }

  render() {
    var TableRows = []

    _.each(this.state.firstNames, (value, index) => {
    TableRows.push(
      <tr>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.firstNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.lastNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.ages[index])}</td>
      </tr>
    )
  })

不管怎样,最新的代码是这样的:

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import dxclogo from './dxclogo.png';
import './App.css';
import Web3 from 'web3';
import _ from 'lodash'
import { Form } from './Form';

//Declaring the ethereum client (initializing) with the url in which the testrpc is running
var ETHEREUM_CLIENT = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))

//These could be dynamically added through input fields, but hard coding for now
var peopleContractABI = [{"constant":true,"inputs":[],"name":"getPeople","outputs":[{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"people","outputs":[{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"age","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_age","type":"bytes32"}],"name":"addPerson","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]

var peopleContractAddress = '0x6c6a4a3e14e25a31fcc323aed7e8395a7df56a6f'

var peopleContract = ETHEREUM_CLIENT.eth.contract(peopleContractABI).at(peopleContractAddress)

class App extends Component{
  constructor(props){
    super(props);
    this.state = {
      firstNames: [],
      lastNames: [],
      ages: []
    }
  }

  componentWillMount(){
    var data = peopleContract.getPeople()
    this.setState({
      firstNames: String(data[0]).split(','),
      lastNames: String(data[1]).split(','),
      ages: String(data[2]).split(',')
    })
  }

  render() {
    var TableRows = []

    _.each(this.state.firstNames, (value, index) => {
    TableRows.push(
      <tr>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.firstNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.lastNames[index])}</td>
        <td>{ETHEREUM_CLIENT.toAscii(this.state.ages[index])}</td>
      </tr>
    )
  })

    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <img src = {dxclogo} className ="App-dxclogo" alt="dxclogo" />
          <h1>Hotel Room Booking dApp</h1>
        </div>
        <div>
          <Form />
          <table className="App-tablePeople">
            <thead>
              <tr>
                <th>First Name </th>
                <th>Last Name </th>
                <th>Age </th>
              </tr>
            </thead>
            <tbody>
              {TableRows}
            </tbody>
          </table>
        </div>
      </div>
    );
  }
}

export default App;

Form.js

import React from 'react';
import Web3 from 'web3';

//Declaring the ethereum client (initializing) with the url in which the testrpc is running
var ETHEREUM_CLIENT = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"))

//These could be dynamically added through input fields, but hard coding for now
var peopleContractABI = [{"constant":true,"inputs":[],"name":"getPeople","outputs":[{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"people","outputs":[{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"age","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_age","type":"bytes32"}],"name":"addPerson","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]

var peopleContractAddress = '0x6c6a4a3e14e25a31fcc323aed7e8395a7df56a6f'

var peopleContract = ETHEREUM_CLIENT.eth.contract(peopleContractABI).at(peopleContractAddress)

//Need to create a variable named accounts in order to know which account
//to make the transactions from
var accounts = ETHEREUM_CLIENT.eth.accounts

//Creating the dynamic input fields for the user to input his/her data
export class Form extends React.Component{
  constructor(props){
  super(props);
  this.state = {
    firstName: 0x0000000000000000000000000000000000000000000000000000000000000000,
    lastName: 0x0000000000000000000000000000000000000000000000000000000000000000,
    age: 0x0000000000000000000000000000000000000000000000000000000000000000,
  }

  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event, key) {
    this.setState({[key]: event.target.value});
  }

  handleSubmit(event) {
    alert('A user was submitted: ' + this.state.firstName + this.state.lastName + this.state.age);
    event.preventdefault();
  }


/*Creating so that person can be added
  componentWillMount(){
     peopleContract.addPerson(this.state.firstName, this.state.lastName, this.state.age, {from: accounts[1], gas: 3000000})
    }
    */

  render() {
    peopleContract.addPerson(this.state.firstName, this.state.lastName, this.state.age, {from: accounts[1], gas: 3000000})
    return(
      <form onSubmit={this.handleSubmit}>
      <h4>Name</h4>
        <input
          type="text"
          placeholder="Name, e.g. Javier"
          value={this.state.firstName}
          onChange={event => this.handleChange(event, 'firstName')}  />
        <div>
        <h4>Last Name</h4>
          <input
            type="text"
            placeholder="Last Name, e.g. Hernandez"
            value={this.state.lastName}
            onChange={event => this.handleChange(event, 'lastName')}/>
        </div>
        <div>
        <h4>Age</h4>
          <input
            type="text"
            placeholder="Age, e.g. 35"
            value={this.state.age}
            name="age"
            onChange={event => this.handleChange(event, 'age')}/>
        </div>
        <input
          type = "submit"
          name = "Submit"
          />
      </form>
    );
  }
}

【讨论】:

    猜你喜欢
    • 2019-04-11
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 2016-08-26
    • 1970-01-01
    相关资源
    最近更新 更多