简体   繁体   English

ReactJS:Dom渲染顺序错误

[英]ReactJS: Dom rendering in wronger order

I have a page that is a table with several columns. 我有一个页面,它是一个包含几列的表。 The user has the ability to sort the entries in the table by several different values; 用户可以按几个不同的值对表中的条目进行排序。 when the user clicks on the header, sorting is performed, and a new render of the page is triggered. 当用户单击标题时,将执行排序,并触发页面的新呈现。 However, while the sorting is performed correctly, the DOM doesn't render in the right order; 但是,尽管排序正确执行,但DOM的渲染顺序不正确。 some elements in the table switch places, but most stay the same. 表中的某些元素切换位置,但大多数保持不变。 When inspecting elements using the react plugin for Chrome, React has things in the correct order; 当使用用于Chrome的react插件检查元素时,React的顺序正确。 it's just that the DOM doesn't actually match what react thinks is going on. 只是DOM实际上与react认为正在进行的事情不匹配。

My code is as follows: 我的代码如下:

var BinData = React.createClass( {
    render: function() {
        return (
            <tr className="databin">    
                <td className="name">
                    <span className="name-field">
                        <span className="databin-name">{this.props.data.Name ? this.props.data.Name: "Databin Name"}</span>
                        <span className="wdd-icon-edit-name"></span>
                    </span>
                </td>
                <td className="id">{this.props.data.ShortID ? this.props.data.ShortID: "None"}</td>
                <td className="date">{this.props.data.formatedLatestTimestamp}</td>
                <td className="url"><a href={this.props.data.ShortURL}>{this.props.data.ShortURL}</a></td>
                <td className="size">{this.props.data.Size}</td>
                <td className="owner">{this.props.data.Owner}</td>
                <td className="actions"><span className="icon-container"><span className="wdd-icon-wolfram-alpha"><br /></span><span className="text analyze">Analyze in Wolfram|Alpha</span></span><span className="icon-container"><span className="wdd-icon-wolfram-language-small"><br /></span><span className="text explore">Open in Wolfram Language</span></span><span className="icon-container"><span className="wdd-icon-download"><br /></span><span className="text download">Download raw data</span></span><span className="icon-container"><span className="wdd-icon-collaborate"><br /></span><span className="text access">Access settings</span></span><span className="icon-container"><span className="wdd-icon-delete"><br /></span><span className="text delete">Remove from my list</span></span></td>
            </tr>

        );
    }
});


var BinList = React.createClass( {
    getInitialState: function() {
        return {
            sorting: "Date"
        };
    },

    sortByName: function(bins,selected) {
        function compare(a,b) {
            if (a.Name < b.Name) {
                return -1;
            }
            if (a.Name > b.Name) {
                return 1;
           }
           return 0;
        }
        if (selected == "My Databins") {
            bins.Creator.sort(compare);
        }
        else if (selected == "Recent Databins") {
            bins.Contributor.sort(compare);
        }
        else {
            bins.SharedWithMe.sort(compare);
        }
        this.setState({sorting: "Name"});
    },

    sortByDate : function(bins,selected) {
        function compare(a,b) {
            return b.LatestTimestamp - a.LatestTimestamp;
        }
        if (selected == "My Databins") {
            bins.Creator.sort(compare);
        }
        else if (selected == "Recent Databins") {
            bins.Contributor.sort(compare);
        }
        else {
            bins.SharedWithMe.sort(compare);
        }

        this.setState({sorting: "Date"});
    },

    sortByOwner: function(bins,selected) {
        function compare(a,b) {
            if (a.Owner < b.Owner) {
                return -1;
            }
            if (a.Owner > b.Owner) {
                return 1;
            }
            return 0;
        }
        if (selected == "My Databins") {
            bins.Creator.sort(compare);
        }
        else if (selected == "Recent Databins") {
            bins.Contributor.sort(compare);
        }
        else {
            bins.SharedWithMe.sort(compare);
        }
        this.setState({sorting: "Owner"});
    },

    sortBySize: function(bins,selected) {
        function compare(a,b) {
            return b.Size - a.Size;
        }
        if (selected == "My Databins") {
            bins.Creator.sort(compare);
        }
        else if (selected == "Recent Databins") {
            bins.Contributor.sort(compare);
        }
        else {
            bins.SharedWithMe.sort(compare);
        }

        this.setState({sorting: "Size"});
    },

    refresh: function() {
        console.log("in refresh");
        this.forceUpdate();
    },

    render: function() {
        var rows = [];
        if (this.props.selected == "My Databins") {
            if (this.props.data.Creator) {
                this.props.data.Creator.forEach(function(bin) {
                    rows.push(<BinData data={bin} key={bin.UUID}/>);
                });
            };
        }
        else if (this.props.selected == "Recent Databins") {
            if (this.props.data.Contributor) {
                this.props.data.Contributor.forEach(function(bin) {
                    rows.push(<BinData data={bin} key={bin.UUID}/>);
                });
            };

        }
        else {
            if (this.props.data.SharedWithMe) {
                this.props.data.SharedWithMe.forEach(function(bin) {
                    rows.push(<BinData data={bin} key={bin.UUID}/>);
                });
            };
        }

        return (
            <section>
                {rows.length > 0 ?
                <table className="databins-list">
                    <thead>
                        <tr className="table-head">
                            <th className="head-names"><a className="sort descending" href="#" onClick={this.sortByName.bind(this,this.props.data, this.props.selected)}>Databin Name {this.state.sorting == "Name" ? <span className="triangle-down"></span>: ""}</a></th>
                            <th className="head-ids">Databin ID</th>
                            <th className="head-dates"><a className="sort" href="#" onClick={this.sortByDate.bind(this,this.props.data,this.props.selected)}>Latest Entry {this.state.sorting == "Date" ? <span className="triangle-down"></span>:""}</a></th>
                            <th className="head-urls">Databin Url</th>
                            <th className="head-sizes"><a className="sort" href="#" onClick={this.sortBySize.bind(this,this.props.data,this.props.selected)}>Size {this.state.sorting=="Size" ? <span className="triangle-down"></span>:""}</a></th> 
                            <th className="head-owners"><a className="sort" href="#" onClick={this.sortByOwner.bind(this,this.props.data,this.props.selected)}>Owner {this.state.sorting=="Owner" ? <span className="triangle-down"></span>:""}</a></th>
                            <th className="head-actions"><a className="refresh" onClick={this.refresh.bind(this)}>Refresh databins <span className="wdd-icon-refresh"></span></a></th> 
                        </tr>
                    </thead>
                    <tbody> {rows} </tbody>
                </table> :
                <AdminZeroState selected={this.props.selected} />
                }
            </section>

        );

    }
});

Does anyone have any idea why what is rendered in the DOM doesn't match what react thinks is going on? 有谁知道为什么DOM中呈现的内容与react所认为的不符?

I'm not sure exactly why these kinds of problems happen, but I've seen similar redraw errors. 我不确定为什么会发生此类问题,但是我看到了类似的重绘错误。 I would advise adding a key attribute to the table element. 我建议将key属性添加到table元素。 Whenever the key attribute changes, the entire table will re-render. 每当key属性更改时,整个表将重新呈现。 This is useful because I think the problem comes from React and the DOM getting out of sync with things being sorted. 这很有用,因为我认为问题出在React和DOM与正在排序的事物不同步。 If your key value changes whenever things are sorted (including the type of sort in the key name, for example), then I think that will work. 如果您的键值在每次排序时都发生变化(例如,包括键名中的排序类型),那么我认为这会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM