2016-08-16 138 views
1

一個故事:組件掛載後設置狀態?

我有一個服務器呈現,但我的應用程序的某些部分不能在那裏完成,因爲他們使用文檔(反應藝術庫在畫布上繪圖)。 我無法呈現所有內容,因爲反應會說從服務器和客戶端收到的代碼不一樣。

所以我的解決方案是渲染我的應用程序在服務器上的一部分,然後渲染這部分在客戶端,並在下一幀,呈現一切無法呈現在客戶端上。

所以我想在componentDidMount使用setState,引發DOM更新,所以它可以包含不能在服務器上進行渲染渲染客戶端部分,但eslint說,這是不好的componentDidMount設置狀態。從邏輯上說,我不能說在這種情況下爲什麼它不好。一般來說它不好,因爲它會觸發DOM更新,但在我的情況下,這是我真正需要的。

你會在這種情況下建議什麼?

編輯1: 固定錯字,我的意思是componentDidMountcomponentDidUpdate

編輯2: Here是同一個問題,但他們使用改變狀態componentDidMount作爲一種解決方法。

+0

看一看[文件](https://facebook.github.io/react/ 'getInitialState'的docs/component-specs.html#getinitialstate)。 –

+0

'getInitialState'用於設置初始值,但我沒有問題。我的問題是:「組件安裝後如何更改狀態?」 –

回答

0

嘗試設置狀態componentWillMountcomponentWillUpdate

請注意componentWillMount,它也可以稱爲服務器端。

+0

我無法在'componentWillMount'中設置狀態,因爲它會將不同的數據呈現給我從服務器獲得的數據。 –

+0

我不能在'componentWillUpdate'做到這一點,它不是在第一渲染調用,它是不是在這種情況下被調用。我的問題不是「在哪裏設置狀態」,問題是:「組件安裝後如何更改狀態?」或上面描述的問題的任何其他選擇。 –

0

我從你的問題中瞭解到,組裝完成後,服務器和客戶端上的數據會發生變化,並且希望組件與更改數據保持同步。 我建議你看一下反應的通量或還原結構。例如,flux是以一種方式實現的,即當組件中的任何內容發生更改時,它會觸發操作並監聽存儲。當存儲中的任何內容改變時,組件將重新呈現它自己。

+0

我已經使用了redux,但這是一個不同的問題。我的數據沒有改變,我會在服務器上渲染所有東西,我沒有任何痛苦,因爲我不使用無法在服務器上使用的庫(在我的情況下爲react-art)。再次,我想知道如何在安裝應用程序後觸發組件更新。這是我需要的事件,但我在componentDidMount中設置狀態不允許在airbnb eslint中使用。 –

0

我想知道如何在安裝應用程序後觸發組件更新。

在React中,將狀態「推」到組件上的傳統方法是使用props而不是state。如果您的應用程序需要獲取客戶端信息並相應地調整組件state,則應執行componentWillReceiveProps。 。

如果你覺得在服務器上渲染和瀏覽器的狀態是一樣的那種,並且不希望跟蹤的麻煩,其性質屬於this.state v this.props,我建議類似如下:

componentWillReceiveProps(nextProps) { 
    this.setState(Object.assign({}, this.state, nextProps)); 
} 

這會將傳遞的屬性合併到組件狀態,以便可以使用this.state訪問它們。

+0

我的問題不在於改變狀態,我的狀態一切都很好,不應該改變。問題是我的客戶端代碼與服務器端代碼不同。從服務器發送html後,我有一個空容器,在客戶端,我有一個數據在那裏。我無法在服務器上渲染這些東西。所以我有警告:「React試圖在容器中重用標記,但校驗和無效。」所以我想從服務器呈現html,然後添加客戶端部分。這就是爲什麼我需要一個回調,甚至可以在我的狀態下更改某些屬性並呈現客戶端部分的處理程序。 –

+0

如果我可以在沒有任何黑客的情況下渲染一次,這將是完美的,但我會收到警告。 –

+0

@RossKhanas我的回答並沒有描述黑客攻擊,而是「改變我的州的一些財產」的正常方式。看來你的描述這個問題的任何嘗試都沒有澄清它。考慮在你的問題中添加一些代碼示例,並解釋爲什麼簡單地將客戶端數據作爲道具傳遞並不能解決問題。 –

0

請參閱this鏈接關於ReactJS - Component Life Cycle。 您應該使用componentWillMount週期。在渲染之前,服務器端和客戶端都會執行componentWillMount

+0

我不能那樣做,因爲我無法在服務器上渲染我的應用程序的一部分,'react-art'具有中斷服務器渲染的窗口依賴項。 –

+0

但我可以稍後檢查一個相關的技巧。也許它會有所幫助。 –

+0

它可以用於第一次呈現,但不能,因爲當頁面呈現時,其html與從服務器發送的HTML不同。所以我有一個警告。這就是爲什麼我想要進行這種回調,以便在下一幀中呈現客戶端部分。 –

1

我剛剛編寫了一個類似的情況,並愉快地使用componentDidMount禁用ESLint的警告。恕我直言,它是完全有效的,只有在通用的渲染場景。

爲什麼:在componentDidMount使用discouraged的setState因爲你會觸發額外的,不必要的渲染。

但是,在您想要區分服務器和客戶端行爲的通用場景中,您需要額外的渲染,並且爲了防止'無法重用標記'錯誤,您需要在反應與服務器呈現的DOM。簡而言之:無論如何你都會渲染兩次。

但是,我不建議在葉/啞組件中編寫此行爲,因爲這樣做需要假定愚蠢的組件具有其環境(客戶端/服務器)的一些知識並呈現設計問題。創建一個可以設置愚蠢組件的道具的組件將是顯而易見的解決方案。的setStatecomponentDidMount

0

防止使用。

更新狀態後一個部件安裝將觸發第二render()呼叫,並可能導致財產/佈局抖動。 下面的模式被認爲是警告:

class MyComponent extends React.Component { 
    componentDidMount(){ 
     this.setState({ 
      data: data 
     }); 
    } 
} 

以下模式不被視爲警告:

class MyComponent extends React.Component { 
    constructor(){ 
     this.setState({ 
      data: data 
     }); 
    } 

    componentDidMount(){ 
     ... 
    } 
}