2017-10-31 8 views
0

Reactコンポーネントのtableにデータをロードしています。私はmaterialize CSS frameworkからテーブルを使用してデータを表示しています。私はテーブルのデータを見ることができます。私はW3school.comのtable sort functionを使用しています。 headerをクリックしてsortTable functionに電話するとすぐに、私はTypeError: Table is nullというエラーメッセージが表示されます。エラーを生成する行はrows = table.getElementsByTagName('TR');です。私はテーブルのデータを見ることができますが、なぜこのエラーが出るのか理解できません。私のコードは次のようになります。テーブルのデータを見ることはできますが、なぜ `table is null`というエラーが表示されるのですか?

import React, { Component } from 'react'; 

class newsList extends Component { 
    constructor(props) { 
     super(props) 
     window.info = []; 
    } 

    render() { 
     this.props.arr.result ? window.info.push(this.props.arr.result) : null 

     var result = window.info.map(item => (
      <tbody key={item.id}> 
       <tr> 
        <td>{item.profileInfo.profileName}</td> 
        <td>{item.rows[0][0]}</td> 
        <td>{item.rows[0][1]}</td> 
        <td>{item.rows[0][2]}</td> 
        <td> 
         <a href="#!" className="secondary-content"> 
          <i className="material-icons"> 
           send 
         </i> 
         </a> 
        </td> 
       </tr> 
      </tbody>)) 

     //Sort function starts here. 
     const sortTable = (n) => { 
      console.log(window.info); 
      var table, rows, switching, i, x, y, shouldSwitch, dir, switchCount = 0; 
      table = document.getElementById('#dataTable'); 
      console.log(table); 
      switching = true; 

      //Sort the sorting direction to ascending: 
      dir = 'asc'; 

      //Make a loop that will continue until no switching has been done: 
      while (switching) { 

       //Start by saying: no switching is done: 
       switching = false; 

       rows = table.getElementsByTagName('TR'); 

       //Loop through all table rows except the headers: 
       for (i = 1; i < (rows.length - 1); i++) { 

        //Start by saying there should be no switching: 
        shouldSwitch = false; 

        //Compare the two elements: 
        x = rows[i].getElementsByTagName('TD')[n]; 
        y = rows[i].getElementsByTagName('TD')[n]; 

        //Switch the rows: 
        if (dir === 'asc') { 
         if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) { 
          shouldSwitch = true; 
          break; 
         } 
        } else if (dir === 'desc') { 
         if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) { 
          shouldSwitch = true; 
          break; 
         } 
        } 
       } 
       if (shouldSwitch) { 
        //If a switch has been done marked, make the switch and mark that a switch has been done: 
        rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); 
        switching = true; 

        //Each time a switch is done, increase this count by 1: 
        switchCount++; 
       } else { 
        //If no Switching has been done AND the direction is 'asc' set the direction to 'desc' and run the while loop again. 
        if (switchCount === 0 && dir === 'asc') { 
         dir = 'desc'; 
         switching = true; 
        } 
       } 
      } 
     } 

     return (
      <div> 
       <table id="dataTable" className="responsive-table"> 
        <thead> 
         <tr> 
          <th onClick={() => sortTable(0)}>Account Name</th> 
          <th>Sessions</th> 
          <th>Bounces</th> 
          <th>Users</th> 
         </tr> 
        </thead> 
        {result} 
       </table> 
      </div> 
     ) 
    } 
} 

export default newsList; 
+1

'document.getElementId'はIDを探していることを示すために'# '記号を必要としないので、あなたが使っているメソッドのために既にそれを知っています。 'document.getElementById( 'dataTable')'のために。つまり、ReactとDOM操作を混在させるのは恐ろしい考えです。 – Icepickle

+0

@Icepickleはい、それはひどい考えですが、私はReactのドキュメントから 'setState'を理解するのが難しく、別の方法は知らないです。 – Parth

+0

それからあなたは本当に基礎に戻って、ここでやっていることがあなたに将来の頭痛を与えるでしょう。あなたが必要とするテーブルを並べ替えるだけの大きな問題ではない場合は、ここで一緒にハッキングしているものを続行しないでください – Icepickle

答えて

1

コメントに答えたように、あなたがあなたのテーブルを取得するためにdocument.getElementByIdメソッドを使用しているので、あなたが受けているの誤差があるが、あなたはハッシュ(#)記号が含まれ、これdocument.getElementById関数はidに正確に一致するパラメータを期待しているので、必要ありません。理論的にはdataTable、それ以上は何もありません;

今、私は理論的に言っています。つまり、あなたはReactを使用しているように見え、DOM操作と混合します。 Reactは仮想DOMと連動し、状態の何かが変わったときにすぐにデータを再描画するので、これら2つを混在させるのは悪い考えです。しかし、あなたがDOMを操作するときに通知されることはありません。そのような面白いことが起こる可能性があります。

ソート方法が意図したとおりに動作しない可能性があります。正直言って、このような場合に何がうまくいかないのかをデバッグしなければならない人になりたくありません。

それでは、あなたのコードの上にビットを手放す:

constructor(props) { 
    super(props) 
    window.info = []; 
} 

すでに非常に興味深いスタートつまり、グローバル変数で物事をミックスするようだと、このコンポーネントは、一度だけ使用することができることを私に語りましたなぜ私はあなたがそれをやりたいのか分からないが、私はあなたに今あなたに言うことができる、本当にすべきではない。コンストラクタでは、initial stateの設定があります。おそらく、いくつかのメソッドバインディングはthisですが、それはコンストラクタを使ってグローバルオブジェクトを操作しないことです!

render() { 
    this.props.arr.result ? window.info.push(this.props.arr.result) : null 

これは、あなたが小道具を通じて、いくつかの配列を受けている、とあなたは我々の前に見たそのグローバルオブジェクトの内部でそれらをプッシュするように見える、本当に私の想像を超えて行く理由のために、とあれば、それがさらに面白くしますそれはない、我々はnullです。彼らは感覚が

var result = window.info.map(item => (
    <tbody key={item.id}> 

良いことはありません。このようなコード行は、あなたがここにマッピングして、後で使用するために、結果セットを作成し、なぜに少なくともコメントに値するが、好ましくは、そこにあるべきではありません。この方法は、あなたのエラーがどこから来るか、よくあるが、それを削除してください...それは面白いグローバル変数との代わりにthis.props.arr.result、およびないでマッピングするために、より理にかなっていること

//Sort function starts here. 
const sortTable = (n) => { 

を注意すべきです、そのようなソートアルゴリズムを使用する理由はまったくなく、変化する州や小道具の外でDOMを操作したり、店舗やレデューサーで作業したりしないでください。この方法は本当にここにはないはずです。私、それはそこにコードの最良のコメント部分ではあるがまた、本当に、この方法でより深く詳細に見たくない、それは

return (
    <div> 
     <table id="dataTable" className="responsive-table"> 
      <thead> 
       <tr> 
        <th onClick={() => sortTable(0)}>Account Name</th> 
        <th>Sessions</th> 
        <th>Bounces</th> 
        <th>Users</th> 
       </tr> 
      </thead> 
      {result} 
     </table> 
    </div> 
) 

を削除する必要があるコードのこの部分が反応しているように見える:)主要な批評のポイントはテーブルのid属性になりますが、Reactアプリケーションには場所がありません。テーブルを内部呼び出し可能にする場合は、ref=((e) => this.table = eコールバックを使用することができます。そのため、追跡する要素と内部的に対話することができます。

あなたが使用している技術についての情報を提供したいだけでなく、ソートや状態や表を扱う別の方法も提供したいと思います。次のコードを実行してください。

2つのプレゼンテーションコンポーネント(TableHeader、TableRow)と1つのコンテナコンポーネント(Table)があります。 /以上である必要がありますが、(ちょうど基本的に扱っても)私は、初期状態で動作するようにどのように表示およびソート管理にかなり興味があった

const TableHeader = ({ columns, onClick, activeColname, isDescending }) => { 
 
    
 
    return <thead> 
 
    { columns.map((col, key) => <th className={activeColname === col.name ? 'sort ' + (isDescending ? 'descending': 'ascending') : ''} key={`header${key}`} onClick={() => onClick(col)}>{col.title}</th>) } 
 
    </thead>; 
 
}; 
 

 
const TableRow = ({ row, columns }) => { 
 
    return <tr> 
 
    { columns.map((col, key) => <td key={`cell${key}`}>{ row[col.name] }</td>) } 
 
    </tr>; 
 
}; 
 

 
class Table extends React.Component { 
 
    constructor() { 
 
    super(); 
 
    this.state = { 
 
     order: null 
 
    }; 
 
    } 
 
    columnClicked(column) { 
 
    console.log('got clicked ', column); 
 
    let { order } = this.state; 
 
    this.setState({ 
 
     order: { 
 
     name: column.name, 
 
     descending: order && order.name === column.name && !order.descending 
 
     } 
 
    }); 
 
    } 
 
    render() { 
 
    let { columns, rows } = this.props; 
 
    let { order } = this.state; 
 
    if (order) { 
 
     // sort, if necessary 
 
     let { name, descending } = order; 
 
     console.log(`ordering by ${name} in ${descending}`); 
 
     rows = [...rows].sort((a, b) => (a[name] > b[name] ? 1 : -1) * (descending ? -1 : 1)); 
 
    } 
 
    return <table> 
 
     <TableHeader columns={columns} activeColname={order && order.name} isDescending={order && order.descending} onClick={(...args) => this.columnClicked(...args)} /> 
 
     <tbody> 
 
     { rows.map((row, key) => <TableRow row={row} columns={columns} key={row.id} />) } 
 
     </tbody> 
 
     </table>; 
 
    } 
 
}; 
 

 
const columns = [ 
 
    { title: 'Team', name: 'team' }, 
 
    { title: 'Played', name: 'played' }, 
 
    { title: 'Won', name: 'won' }, 
 
    { title: 'Equal', name: 'equal' }, 
 
    { title: 'Lost', name: 'lost' } 
 
]; 
 

 
const data = [ 
 
    { id: 0, team: 'PSG', played: 4, won: 4, equal: 0, lost: 0 }, 
 
    { id: 1, team: 'Bayern munchen', played: 4, won: 3, equal: 0, lost: 1 }, 
 
    { id: 2, team: 'Celtic Glasgow', played: 4, won: 1, equal: 0, lost: 3 }, 
 
    { id: 3, team: 'RSCA Anderlecht', played: 4, won: 0, equal: 0, lost: 4 } 
 
]; 
 

 
ReactDOM.render(<Table columns={columns} rows={data} />, document.querySelector('#app'));
.sort { 
 
    text-decoration: underline; 
 
} 
 
.ascending::after { 
 
    content: '▲'; 
 
} 
 
.descending::after { 
 
    content: '▼'; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 
 
<div id="app"></div>

ことができ、私は、React documentationへのリンクを追加しました私は本当にあなたがそれらを読んでいくまで時間がかかることを願っています;)

関連する問題