亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

ReactJS-提升狀態與保持本地狀態

ReactJS-提升狀態與保持本地狀態

慕容3067478 2019-10-21 10:42:41
在我公司,我們正在將Web應用程序的前端遷移到ReactJS。我們正在使用create-react-app(更新為v16),而沒有Redux?,F在,我停留在頁面上,該頁面可以通過以下圖像簡化:在componentDidMount()MainContainer方法中,使用相同的后端請求檢索由三個組件(SearchableList,SelectableList和Map)顯示的數據。然后,此請求的結果存儲在MainContainer的狀態中,其結構大致如下:state.allData = {  left: {    data: [ ... ]  },  right: {    data: [ ... ],    pins: [ ... ]  }}LeftContainer state.allData.left從MainContainer 接收作為道具,并props.left.data再次作為道具傳遞到SearchableList。RightContainer state.allData.right從MainContainer 接收作為道具,并傳遞props.right.data到SelectableList和props.right.pinsMap。SelectableList顯示一個復選框,允許對其項目執行操作。每當對SelectableList組件的一項操作發生時,它可能會對Map引腳產生副作用。我決定在RightContainer狀態下存儲一個列表,該列表保留SelectableList顯示的所有項目ID。此列表作為道具傳遞給SelectableList和Map。然后,我將一個回調傳遞給SelectableList,該回調使每當進行選擇時都會更新RightContainer中的ID列表;新道具同時出現在SelectableList和Map中,因此render()在這兩個組件中都被稱為。它工作正常,有助于將Rightable容器中的SelectableList和Map可能發生的所有事情保留在RightContainer中,但是我想問這對于提升狀態和事實真相的概念是否正確。作為可行的替代方案,我想到了向MainContainer中的_selected每個項目添加一個屬性state.right.data,并將select回調三級傳遞給SelectableList,以處理MainContainer中的所有可能動作。但是,一旦發生選擇事件,這最終將強制加載LeftContainer和RightContainer,從而引入了實現邏輯的需求,例如shouldComponentUpdate()避免無用的邏輯,render()尤其是在LeftContainer中。從體系結構和性能的角度來看,哪種是/可能是優化此頁面的最佳解決方案?您可以在下面摘錄我的組件,以幫助您了解情況。MainContainer.jsclass MainContainer extends React.Component {  constructor(props) {    super(props);    this.state = {      allData: {}    };  }  componentDidMount() {    fetch( ... )      .then((res) => {        this.setState({          allData: res        });      });  }  render() {    return (      <div className="main-container">        <LeftContainer left={state.allData.left} />        <RightContainer right={state.allData.right} />      </div>    );  }}export default MainContainer;RightContainer.jsclass RightContainer extends React.Component {  constructor(props) {    super(props);    this.state = {      selectedItems: [ ... ]    };  }  onDataSelection(e) {    const itemId = e.target.id;    // ... handle itemId and selectedItems ...  }
查看完整描述

3 回答

?
忽然笑

TA貢獻1806條經驗 獲得超5個贊

如React文檔所述


通常,幾個組件需要反映相同的變化數據。我們建議將共享狀態提升到最接近的共同祖先。


對于React應用程序中發生的任何數據更改,應該只有一個“事實來源”。通常,首先將狀態添加到需要呈現的組件。然后,如果其他組件也需要它,則可以將其提升到最接近的共同祖先。與其嘗試在不同組件之間同步狀態,不如依靠自上而下的數據流。


與雙向綁定方法相比,解除狀態涉及編寫更多的“樣板”代碼,但這樣做的好處是,查找和隔離錯誤的工作量較小。由于任何狀態都“存在”于某個組件中,并且僅該一個組件即可更改它,因此大大減少了錯誤的表面積。此外,您可以實現任何自定義邏輯來拒絕或轉換用戶輸入。


因此,從本質上講,您還需要將樹狀結構提升到正在被兄弟姐妹組件使用的狀態。因此,您第selectedItems一個將狀態存儲為狀態的實現RightContainer是完全合理的,并且是一種很好的方法,因為父級不需要了解信息,并且這data是由的兩個child組件共享的,而這兩個組件RightContainer現在只有一個來源真相。


根據您的問題:


作為可行的替代方案,我想到了將_selected屬性添加到中的每個項目中state.right.data,MainContainer并將select回調向下傳遞到三個級別,以SelectableList處理in中的所有可能動作MainContainer


我不同意這是比第一種更好的方法,因為您MainContainer不需要知道selectedItems或處理程序的任何更新。MainContainer對這些州沒有做任何事情,只是將其傳承下去。


考慮到optimise on performance您自己談論實現a的問題shouldComponentUpdate,但是可以通過擴展組件來避免這種情況,該組件通過擴展React.PureComponent本質上實現了and shouldComponentUpdate的shallow比較來實現。stateprops


根據文檔:


如果您的React組件的render()函數在相同的道具和狀態下呈現相同的結果,則React.PureComponen在某些情況下可以使用t來提高性能。


但是,如果多個深度嵌套的組件正在使用同一數據,則使用redux并將該數據存儲在redux狀態是有意義的。這樣,整個應用程序就可以全局訪問它,并且可以在不直接相關的組件之間共享它。


例如考慮以下情況


const App = () => {

    <Router>

         <Route path="/" component={Home}/>

         <Route path="/mypage" component={MyComp}/>

    </Router>

}

現在,如果Home和MyComp都想訪問相同的數據。您可以通過通過renderprop 調用它們,將數據作為來自prop的prop 傳遞。但是,可以通過使用以下connect函數將這兩個組件都連接到Redux狀態來輕松實現


const mapStateToProps = (state) => {

   return {

      data: state.data

   }

}


export connect(mapStateToProps)(Home);

和類似的MyComp。易于配置操作以更新相關信息


同樣,為您的應用程序配置Redux特別容易,您將能夠在單個化簡器中存儲與相同內容相關的數據。這樣,您還可以模塊化您的應用程序數據


查看完整回答
反對 回復 2019-10-21
?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

通過使用Redux,您可以避免此類回調并在單個存儲中維護整個狀態-因此,使您的父組件連接組件-并使左右組件啞巴-只需將您從父組件獲得的道具傳遞給子組件-然后您在這種情況下,不必擔心回調。


查看完整回答
反對 回復 2019-10-21
  • 3 回答
  • 0 關注
  • 759 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號