簡體   English   中英

無法為react.js組件設置密鑰

[英]Unable to set the key for react.js components

似乎最瑣碎的任務再次使我的項目停頓了。 這是我的情況:

我在ASP.NET 4.5 MVC 6 SPA中使用react.js。 我的設計使我在三個主要區域使用了react:頂部菜單,側面菜單和主要內容區域。 由於不同區域的時間和負載要求,我有3個獨立的React組件層次結構,每個主要部分一個。 也許那是那里問題的一部分,但是在某個地方,我想到了這是可以接受的。

因此,在某一時刻,我從Web服務中提取了一個頂層菜單節點列表,並將它們綁定到頂層菜單react組件,然后對側面菜單執行相同的操作。 當有人單擊菜單項之一時,它將新數據加載到內容面板區域中,這些是我加載到div中的react組件。

一切工作都按預期進行,直到我嘗試在內容面板中卸載該組件,然后再向其中加載新組件。 當我通過我的div調用ReactDOM.unmountComponentAtNode() ,我得到以下信息:

Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the same數據反應: .0(…)

在這一點上,我有一些疑慮:

  • 首先,我不明白為什么在DOM中的各處似乎都需要有React節點,而當我傳入一個我想卸載的特定元素時。 在我指定的DOM元素范圍內,只有一個react組件; 我希望這樣就足夠了。
  • 其次,我多次嘗試在頂級React組件上設置特定鍵均失敗了。 我閱讀並理解了建議/規則,您在創建鍵時必須在組件外部設置鍵,而不是直接在內部從元素上設置鍵,因此我的組件創建為:

    ReactDom.render(<ManageCommunitiesContainer brandData={mcmData} key="manageComms" />, $("#reactRoot")[0]);

我已經為正在使用的三個頂級組件中的每個組件添加了唯一鍵,但是當我在chrome開發人員工具的react插件中檢查它們時,所有這三個組件都具有相同的data-reactid ,即“ 0.0' 。

我已經從內部在子對象上設置了子對象的鍵,在循環內沒有任何問題。 但是在通過javascript添加的頂級組件上,我什么也沒做,導致它們具有有意義的運行時值...一個人必須做什么才能為根組件分配唯一的鍵,從而能夠在以后卸載它們? 因為我無法卸載它們,所以它們堆積在內存中。

謝謝。

React鍵與data-reactid 了解React組件與DOM元素不同。 有一篇不錯的React博客文章 ,解釋了Components,Instances和Elements之間的區別。

我要說的是,嘗試手動卸載組件並渲染全新的樹很難。 當您僅執行初始渲染然后處理狀態以使React更新DOM元素時,React的優勢就會顯示出來。

我的第一個建議是嘗試回到單個組件層次結構。 時序要求可以在根組件的狀態下捕獲。 像這樣:

class TopMenu extends React.Component {
  render() {
    const data = this.props.data;

    if (!data) {
      return <div>Loading...</div>;
    }

    // render your menu with the data provided...
    return <div>{data}</div>;
  }
}

class SideMenu...
class Content...

class Page extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {
      topMenuData: undefined,
      sideMenuData: undefined,
      contentData: undefined
  }

  componentDidMount() {
    // call ready callback provided via props with this instance
    // so someone outside can update our state when data loads
    this.props.ready(this);
  }

  render() {
    return (
      <div>
        <TopMenu data={this.state.topMenuData} />
        <SideMenu data={this.state.sideMenuData} />
        <Content data={this.state.contentData} />
      </div>);
  }
}


// main js code
function pageMounted(page) {
  // register callbacks with your code that is loading data from
  // the server.
  topMenuLoader.then(data => page.setState({ topMenuData: data }));
  sideMenuLoader.then(data => page.setState({ sideMenuData: data }));
  contentLoader.then(data => page.setState({ contentData: data }));
}

React.render(<Page ready={pageMounted} />, rootElement);

通過這種風格,最終您可能可以將加載邏輯移至React組件層次結構本身內的某個位置,並擺脫使外界更新狀態的ready回調。

即使由於約束而無法創建單個組件層次結構,也可以使用該ready回調的相同基本思想來創建3個您從未銷毀的頂級React層次結構,而僅在需要更改setState通過setState提供新數據呈現什么。

幾天后的午夜過后,答案:似乎與我始終使用html包裝標簽相同的元素ID有關。

我認為總是將包含反應.clear()的元素指定為具有相同的id是明智的,因此我可以以編程方式找到它,然后卸載組件,然后將.clear()內容平整以便准備好進行新的標記,無論是否做出反應。

最終,我看到我前一段時間做的一些測試使用的是唯一元素id並按計划進行,因此我現在對它們進行了足夠的更改,以至於相信這是有影響的。 像以往一樣,我還不是100%清楚為什么我的方法會導致它窒息,似乎可以從我坐着的地方采取足夠的合法行動,但是...有。

希望它能在某個時候對某人有所幫助。

暫無
暫無

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

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