【问题标题】:React table sorting is not consistent its keep changing back to default stateReact 表排序不一致,它不断变回默认状态
【发布时间】:2019-09-09 12:01:23
【问题描述】:

当用户单击表头时,我正在处理此反应表排序,它需要对表进行排序,排序正常,但问题是我每秒通过 SignalR 集线器接收新数据,它设置状态 @987654321 @ 到新数据。当用户单击表头时,它会对表进行排序,但又会返回到由新数据更改的新状态。并将已排序的表取消为未排序的。

有什么方法可以保持排序状态并仍然接收数据?

constructor() {
    super()
    this.state = {
        udata: []
    }

    this.onSort = this.onSort.bind(this)

    let connection = new signalR.HubConnectionBuilder()
        .withUrl("/signalserver")
        .build();

    connection.start().then(function () {
    }).catch(function (err) {
        return console.error(err.toString());
    });
    connection.on("APIDataChannel", function (data) {
        this.setState({ udata: data });
        // console.log(data);
    }.bind(this));

    async function start() {
        try {
            await connection.start();
            console.log("connected");
        } catch (err) {
            console.log(err);
            setTimeout(() => start(), 5000);
        }
    };

    connection.onclose(async () => {
        await start();
    });

}

renderItem(item, key) {
    const itemRows = [
        <tr onClick={clickCallback} key={"row-data-" + key}>
            <td>{item.appName}</td>
            <td>
                <h6 className="text-muted"><i className={"fa fa-circle text-c-" + (item.appState === 'STARTED' ? 'green' : 'red') + " f-10 m-r-15"} />{item.appState}</h6>
            </td>
            <td>{item.spaceName}</td>
            <td>
                <h6 className="text-muted">{item.orgName}</h6>
            </td>
            <td>
                <h6 className="text-muted">{new Date(item.appUpdatedAt).toLocaleString()}</h6>
            </td>
        </tr>
    ];

    return itemRows;
}


onSort(event, sortKey) {
    const data = this.state.udata;
    data.sort((a, b) => a[sortKey].localeCompare(b[sortKey]))
    this.setState({ data })
}


render() {

    let allItemRows = [];

    this.state.udata.forEach((item, key) => {
        const perItemRows = this.renderItem(item, key);
        allItemRows = allItemRows.concat(perItemRows);
    });

    return (
        <Aux>
            <Row>
                <Table hover responsive>
                    <thead>
                        <tr>
                            <th onClick={e => this.onSort(e, 'appName')}>App Name</th>
                            <th>State</th>
                            <th>Space</th>
                            <th>Organization</th>
                            <th onClick={e => this.onSort(e, 'appUpdatedAt')}>Updated At</th>
                        </tr>
                    </thead>
                    <tbody>
                        {allItemRows}
                    </tbody>
                </Table>
            </Row>
        </Aux>
    );
}

【问题讨论】:

  • 需要在状态下保存udata吗?我通常将数据存储在它之外。
  • 现在不是真的需要我在状态中保存数据,但在未来,我打算使用全局状态,因为我有类似的 4 个不同环境的页面。在一个地方提取数据然后在整个应用程序中使用它更有意义。
  • 我认为您可以将表格排序设置保存为 state。也许在将它保存到状态之前使用这些设置对 udata 进行排序。
  • 你能告诉我怎么做吗?

标签: javascript reactjs datatables signalr signalr.client


【解决方案1】:

我明天也许可以提供更多帮助。我现在正在使用一台坏了一半的笔记本电脑。

这是一个基本的想法,我的语法可能有点不对。

//might need better default values for sortEvent and sortKey
this.state = {
    udata: [],
    sortEvent: {},
    sortKey: ''
}

connection.on("APIDataChannel", function (data) {
  this.setState({ udata: data });
  // I'm not sure about sortEvent in this context
  onSort(this.state.sortEvent, this.state.sortKey);
  //may need to be a callback like:
  this.setState({ udata: data },onSort(this.state.sortEvent, this.state.sortKey));
   // console.log(data);
}.bind(this));

onSort(event, sortKey, data) {
    this.setState({
      sortEvent: event,
      sortKey: sortKey 
     });
    const data = this.state.udata;
    data.sort((a, b) => a[sortKey].localeCompare(b[sortKey]))
    // I'm not sure what this is doing:
    this.setState({ data })
}

<th onClick={e => this.onSort(e, 'appName', this.state.udata)}>App Name</th>

如果您最终每次都调用它,我也只会在 sort 中设置状态。也许也传递数据。所以:

//might need better default values for sortEvent and sortKey
this.state = {
    udata: [],
    sortEvent: {},
    sortKey: ''
}

connection.on("APIDataChannel", function (data) {
  // one onSort call
  onSort(this.state.sortEvent, this.state.sortKey, data);
   // console.log(data);
}.bind(this));

onSort(event, sortKey, data) {
    data.sort((a, b) => a[sortKey].localeCompare(b[sortKey]))
    // Set the state of everything once:
    this.setState({
      sortEvent: event,
      sortKey: sortKey,
      udata: data 
     });
}
<th onClick={e => this.onSort(e, 'appName', this.state.udata)}>App Name</th>

我总是三思而后行。我真的不会将数据保存到状态。我做:

//might need better default values for sortEvent and sortKey
this.state = {
    sortEvent: {},
    sortKey: ''
},
this.data = [];

connection.on("APIDataChannel", function (data) {
  this.data = data;
  // one onSort call
  onSort(this.state.sortEvent, this.state.sortKey);
   // console.log(data);
}.bind(this));

onSort(event, sortKey) {
    this.data.sort((a, b) => a[sortKey].localeCompare(b[sortKey]))
    // Set the state of everything once:
    this.setState({
      sortEvent: event,
      sortKey: sortKey,
      //if you really need to set data to state you could do it here
      udata: data 
     });
}
<th onClick={e => this.onSort(e, 'appName')}>App Name</th>

【讨论】:

  • 我尝试了您的解决方案,但每次页面加载以加载数据时,我都必须单击表头。
  • @Sam 有错误吗?没有行的表?您可以记录数据并查看它是否至少正确排序?我还想办法将你的 forEach 循环移出渲染。渲染的开销很大。我会查看组件生命周期:reactjs.org/docs/react-component.html#the-component-lifecycle
  • 没有错误,并且排序正确,但我每次都必须通过单击标题来触发事件
  • 请您只发布一个干净的解决方案,而不是 3 个解决方案
  • 我相信 Joe Fitzsimmons 的基本思想是 sortKey 应该存储在 state 对象中是绝对正确的。 onSort 应该将排序键值存储到状态。像这样:`this.setState({sortKey})` 然后你可以使用这个state.sortKey 值对传递给"APIDataChannel" 事件处理程序的数据数组进行排序,然后再将其分配给state.udata。这意味着一旦收到数据,就应该根据[存储在状态中]sortKey 对它们进行排序,并且仅在分配给state.udata 之后。
猜你喜欢
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2020-08-31
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多