我正在将一些数据加载到table
组件中的React
。我正在使用materialize CSS framework
中的表格显示数据。我可以在表格中看到数据。我正在使用W3school.com的table sort function
。只要我点击header
拨打sortTable function
,我就会收到TypeError: Table is null
错误消息。创建错误的行是rows = table.getElementsByTagName('TR');
。虽然我可以看到表中的数据,但我无法理解为什么会出现此错误?我的代码如下所示:
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;
答案 0 :(得分:1)
因此,正如评论中所回答的那样,您收到的错误是因为您使用document.getElementById
方法获取表格,但是您包含了哈希(#)符号,这不是必需的{ {1}}函数需要一个与id完全匹配的参数,所以它理论上应该是document.getElementById
,仅此而已,不能少;)
现在,我在理论上说,并且有一个很好的理由,即你似乎正在使用React,并将它与DOM操作混合在一起。混合这两者是一个坏主意,因为React与虚拟DOM一起工作,一旦状态发生变化,它就会重新呈现你的数据。但是,当您开始修改DOM时,它将不会得到通知,因此可能会发生这样有趣的事情。
有一件事是肯定的,你的排序方法可能永远不会按预期工作,说实话,我不想成为那些必须调试在这种情况下出错的人。
让我们稍微讨论你的代码:
dataTable
这已经是一个非常有趣的开始,这告诉我这个组件可以使用一次,因为它似乎与全局变量混合,虽然我不知道为什么你想这样做,我可以告诉你现在已经,你真的不应该。最多,在构造函数中你会发现一些initial state设置,也许是与constructor(props) {
super(props)
window.info = [];
}
的一些方法绑定,但就是这样,不要通过构造函数来操纵全局对象!
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
这个方法很好,你的错误来自,但请删除它,绝对没有理由使用这样的排序算法,并且不要在改变状态或道具之外操纵DOM,与商店或者减少器一起使用。这个方法真的不应该在这里。我也不想用这种方法深入研究,虽然它是那里最好的注释代码,但它应该被删除
//Sort function starts here.
const sortTable = (n) => {
这段代码似乎是React :)批评的一个主要观点是表上的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>
)
属性,它在React应用程序中没有位置。如果你想让你的表在内部可调用,你可以使用ref=((e) => this.table = e
回调,这样你就可以在内部与你想要跟踪的元素进行对话。
请注意,我不仅希望向您提供有关您正在使用的技术的信息,不,我还想以更React的方式为您提供另一种处理排序和状态和表格的方法,所以请随意通过以下代码完成工作。它显示了我最喜欢的比利时队在冠军联赛中的表现有多糟糕,所以我把这些分数排除在外;)
它有2个表示组件(TableHeader,TableRow)和1个容器组件(表),它们可能/应该更多,但我很有兴趣向您展示如何使用初始状态和管理排序(尽管基本上处理)
id
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: '▼';
}
我添加了一些指向React documentation的链接,我真的希望你花一些时间来阅读它们;)