簡體   English   中英

盡管props中的Object發生變化,但React組件未重新渲染

[英]React component not re-rendering, although Object in props changes

我知道,有很多很多相似的問題。** 重復警報! **

但是:我保證,我會仔細檢查所有這些對象。 我現在很確定,這是另一種情況,可能與道具成為物體有關(從我在這里閱讀的內容)。 但無論如何,我無法解決以下問題:

class CsvListDropdown extends Component {
    constructor(props) {
        super(props);
        this.state = { sessions: props.sessions }
        this csvsInSession = this.csvsInSession.bind(this);
    }

    csvsInSession(sessions) {
        return (sessions
            .map(keys => Object.entries(keys)[2][1])
            .map((csv, i) => (
                <option value={csv} key={i}>{csv}</option>
            ))
        )
    }

    render() {
        const { isLoading } = this.props
        if (isLoading) { blablabla.. }
        else {
            return (
                ...
                <select value={this.props.sessions[0].currentCsv}>
                    {this.csvsInSession(this.state.sessions)}
                </select>
                ...
            )
        }
    }
}

export default withTracker(() => {
    const handle = Meteor.subscribe('sessions');
    return {
      isLoading: !handle.ready(),
      sessions: Sessions.find({}).fetch() 
    };
})(CsvListDropdown);

現在,從客戶端,我將另一個文檔寫入Sessions集合,其中包含.csv文件名,而此新的csv文件正在上傳到遠程服務器。 console.log(this.props.sessions)給了我一個數組,它是最新的。 但是組件本身不會重新渲染。

我還不明白的是: console.log(this.state.sessions)返回undefined (注: 狀態

到目前為止我嘗試過的是:

  • {this.csvsInSession(this.props.sessions)} (注意: props
  • withTracker / State / Props添加到父組件,並將sessions對象從stateprops作為參數傳遞給子組件,然后應重新呈現。

  • 強制性升級()

  • componentWillUpdate()

可能也很重要:該組件應該在另一個組件也重新渲染的同時重新渲染(顯示從微服務返回並寫入另一個集合的已上傳CSV的內容)。 后者實際上確實會重新渲染。但是該下拉列表卻沒有。

僅當您調用this.setState()而不執行時, this.state才會更改。 您將使用props的值初始化state ,但僅在首次實例化組件時才在構造函數中進行初始化。 此后,即使props更改,您的組件也可能會重新渲染,但其顯示的內容不會更改,因為state尚未更新。

實際上,似乎沒有任何理由在該組件中以狀態存儲數據。 它也可能是功能性的演示組件:

function CsvListDropdown(props) {
    function csvsInSession(sessions) {
        return (sessions
            .map(keys => Object.entries(keys)[2][1])
            .map((csv, i) => (
                <option value={csv} key={i}>{csv}</option>
            ))
        )
    }

    const { isLoading } = props;
    if (isLoading) { blablabla.. }
    else {
        return (
            ...
            <select>
                {csvsInSession(props.sessions)}
            <select>
            ...
        )
    }
}

通常,除非出於某種原因特別需要存儲內部狀態,否則所有組件都應為無狀態功能組件

現在我終於解決了它,而且事實證明,該組件實際上確實隨時更新,但我沒有注意到它,只是因為數組中的最新項目是悄悄地追加到下拉列表的底部 但是,這並不是我所期望的,因為我以降序排序 發布了該系列。

// server-side
Meteor.publish('sessions', function() {
    return Sessions.find({ userId: this.userId }, { sort: {createdAt: -1} });
});

服務器端似乎是錯誤的排序位置。 它根本沒有作用。 因此,在訂閱時在客戶端排序:

// client-side
export default withTracker(() => {
    const handle = Meteor.subscribe('sessions');
    return {
      isLoading: !handle.ready(),
      sessions: Sessions.find({}, { sort: {createdAt: -1} }).fetch() 
    };
})(App)

我已經從問題中省略了一個重要的細節,那就是如何設置下拉字段的

<select value={this.props.sessions[0].currentCsv}>
    {this.csvsInSession(sessions)}
</select>

因此,我們汲取了以下教訓:如果您認為自己的react組件沒有重新渲染,請在進行假設之前始終檢查是否正確。


作為調試的副作用,我重構了我的組件。 現在, Meteor.subscribe()位於父組件內,該組件包含必須處理sessions對象的所有子代。 然后sessions對象作為道具從父級傳遞到(大)子級。 我認為這種方式更具可讀性,並且更容易維護。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM