Как передать массив в реагировать JS внутри рендера - PullRequest
0 голосов
/ 30 октября 2018

Я разрабатываю приложение IPFS-Ethereum с использованием React JS, где я буду загружать файл XML и анализировать его. У меня проблема с отображением проанализированных данных в виде массива в таблице. Показывает только последний элемент в массиве.

This is the code used for parsing, in console it is showing the two data in the console which is parsed. But in Table it is showing only the last element. I tried using this this.liItem[i]/this.liItem[0] but it is throwing undefined error.

var request = new Request(`https://gateway.ipfs.io/ipfs/${this.state.ipfsHash}`);
fetch(request).then((results) => {
  // results returns XML. lets cast this to a string, then create
  // a new DOM object out of it!
  results
    .text()
    .then((str) => {
      this.state.responseDoc = new DOMParser().parseFromString(str, 'application/xml');
      console.log(this.state.responseDoc);

      this.state.listItem = this.state.responseDoc.getElementsByTagName('Name');
      // console.log(listItem);
      for (this.i = 0; this.i < this.state.listItem.length; this.i++) {
        this.liItem = this.state.responseDoc.getElementsByTagName('Name')[this.i].textContent;
        this.setState({
          liItem: this.state.liItem
        });
        console.log(this.liItem);
      }
    })

Это строка {this.liItem}, используемая в таблице для отображения данных массива. ( ссылка на картинку )

Это мой файл App.js.

import {Table, Grid, Button, Form} из'act-bootstrap '; импортировать React, {Component} из 'response'; import './App.css'; импортировать web3 из './web3'; импортировать ipfs из './ipfs'; импортировать хранилище из './storehash';

class App extends Component {
  state = {
    ipfsHash:null,
    buffer:'',
    ethAddress:'',
    blockNumber:'',
    transactionHash:'',
    gasUsed:'',
    txReceipt: '',
    responseDoc:'',
    listItem:'',
    i:'',
    liItem:[]
  };


  captureFile =(event) => {
    event.stopPropagation()
    event.preventDefault()
    const file = event.target.files[0]
    let reader = new window.FileReader()
    reader.readAsArrayBuffer(file)
    reader.onloadend = () => this.convertToBuffer(reader)    
  };

  convertToBuffer = async(reader) => {
    //file is converted to a buffer to prepare for uploading to IPFS
    const buffer = await Buffer.from(reader.result);
    //set this buffer -using es6 syntax
    this.setState({buffer});
  };

  onClick = async () => {
  try{
      this.setState({blockNumber:"waiting.."});
      this.setState({gasUsed:"waiting..."});

      // get Transaction Receipt in console on click
      // See: https://web3js.readthedocs.io/en/1.0/web3- eth.html#gettransactionreceipt
      await web3.eth.getTransactionReceipt(this.state.transactionHash, (err, txReceipt)=>{
      console.log(err,txReceipt);
        this.setState({txReceipt});
      }); //await for getTransactionReceipt

      await this.setState({blockNumber: this.state.txReceipt.blockNumber});
      await this.setState({gasUsed: this.state.txReceipt.gasUsed});    
    } //try
    catch(error){
    console.log(error);
    } //catch


    var request = new Request(`https://gateway.ipfs.io/ipfs/${this.state.ipfsHash}`);
    fetch(request).then((results) => {
      // results returns XML. lets cast this to a string, then create
      // a new DOM object out of it!
      results
      .text()
      .then(( str ) => {
        this.state.responseDoc = new DOMParser().parseFromString(str, 'application/xml');
        console.log(this.state.responseDoc);

        this.state.listItem  = this.state.responseDoc.getElementsByTagName('Name');
                // console.log(listItem);
        for (this.i=0; this.i<this.state.listItem.length; this.i++){
          this.liItem = this.state.responseDoc.getElementsByTagName('Name')[this.i].textContent;
          this.setState({liItem: this.state.liItem});
          console.log(this.liItem);
        }
      })
    });
  } //onClick

  onSubmit = async (event) => {
    event.preventDefault();

    //bring in user's metamask account address
    const accounts = await web3.eth.getAccounts();

    console.log('Sending from Metamask account: ' + accounts[0]);

    //obtain contract address from storehash.js
    const ethAddress= await storehash.options.address;
    this.setState({ethAddress});

    //save document to IPFS,return its hash#, and set hash# to state
    //https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/FILES.md#add 
    await ipfs.add(this.state.buffer, (err, ipfsHash) => {
      console.log(err,ipfsHash);
      //setState by setting ipfsHash to ipfsHash[0].hash 
      this.setState({ ipfsHash:ipfsHash[0].hash });


      // call Ethereum contract method "sendHash" and .send IPFS hash to etheruem contract 
      //return the transaction hash from the ethereum contract
      //see, this https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#methods-mymethod-send

      storehash.methods.sendHash(this.state.ipfsHash).send({
          from: accounts[0] 
        }, (error, transactionHash) => {
          console.log(transactionHash);
          this.setState({transactionHash});
        }

      ); //storehash 
    }) //await ipfs.add
  }; //onSubmit 


  render() {

    return (
      <div className="App">
        <header className="App-header">
          <h1>
            {" "}
            Ethereum and InterPlanetary File System(IPFS) with Create React App
          </h1>
        </header>
        <hr />

        <Grid>
          <h3> Choose file to send to IPFS </h3>
          <Form onSubmit={this.onSubmit}>
            <input type="file" onChange={this.captureFile} />
            <Button bsStyle="primary" type="submit">
              Send it
            </Button>
          </Form>
          <br />

          <img
            src={`https://ipfs.io/ipfs/${this.state.ipfsHash}`}
            alt=""
            style={{ height: 200 }}
          />

          <hr />
          <Button onClick={this.onClick}> Get Transaction Receipt </Button>
          <Table bordered responsive>
            <thead>
              <tr>
                <th>Tx Receipt Category</th>
                <th>Values</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>IPFS Hash # stored on Eth Contract</td>
                <td>{this.state.ipfsHash}</td>
              </tr>
              <tr>
                <td>Ethereum Contract Address</td>
                <td>{this.state.ethAddress}</td>
              </tr>
              <tr>
                <td>Tx Hash # </td>
                <td>{this.state.transactionHash}</td>
              </tr>
              <tr>
                <td>Block Number # </td>
                <td>{this.state.blockNumber}</td>
              </tr>
              <tr>
                <td>Gas Used</td>
                <td>{this.state.gasUsed}</td>
              </tr>
              <tr>
                <td>XML</td>
                <td>{this.liItem}</td>
              </tr>
            </tbody>
          </Table>
        </Grid>
      </div>
    );
    //render
  }
}

export default App;

Я надеюсь, что вы, люди, поймете мой вопрос и дадите мне решение. Спасибо

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

В коде было мало изменений, и это сработало для меня.

var request = new Request(`https://gateway.ipfs.io/ipfs/${this.state.ipfsHash}`);
  fetch(request).then((results) => {
    // results returns XML. lets cast this to a string, then create
    // a new DOM object out of it!
    //Array Declaration
    var values=[];
    results
      .text()
      .then(( str ) => {
        this.state.responseDoc = new DOMParser().parseFromString(str, 'application/xml');
        console.log(this.state.responseDoc);

        this.state.listItem  = this.state.responseDoc.getElementsByTagName('Name');
        for (this.i=0; this.i<this.state.listItem.length; this.i++){
        //Pushing values into the array
        values.push(this.state.responseDoc.getElementsByTagName('Name')[this.i].textContent);
        console.log(values);
         }
        this.setState({liItem: values});
      })
    });

 And down in the render I used this for displaying
 <tr>
 <td>
 XML
 </td>
 <td>
 {this.state.liItem.map(x => {return x})}
 </td>
 </tr>
0 голосов
/ 30 октября 2018

Попробуйте это:

<tr>
    <td>XML</td>
    <td>{this.liItem.map((value, index) => {
        <p key={index}>{value}</p>
    })}</td>
</tr>

с этим вы должны получить все записи в отдельной строке (причина p равна w = 100%)

...