[英]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
對象從state
或props
作為參數傳遞給子組件,然后應重新呈現。
強制性升級()
可能也很重要:該組件應該在另一個組件也重新渲染的同時重新渲染(顯示從微服務返回並寫入另一個集合的已上傳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.