2017-09-06 47 views
0

我試圖用反應實現簡單的頁面 - 現在我已經得到了主要成分叫做佈局:渲染菜單子組件變化後作出反應

import * as React from 'react'; 
import { NavMenu } from './NavMenu'; 
import SummaryBanner from './SummaryBanner'; 

export class Layout extends React.Component<{}, {}> { 
    public render() { 
     return <div className='container-fluid'> 
      <div className='row'> 
       <div className='col-sm-3'> 
        <NavMenu /> 
        <SummaryBanner /> 
       </div> 
       <div className='col-sm-9'> 
        { this.props.children } 
       </div> 
      </div> 
     </div>; 
    } 
} 

在兒童this.props.children定義我已經有組件代表簡單的嚮導 - 形式只有幾個步驟 - 每個部分都是分開提交的。 元器件SummaryBanner包含嚮導的步驟已經提交/所有數據是通過使用提取方法/主叫API接收。 唯一的問題是,部分SummaryBanner沒有在提交重新呈現。

它是如何可能做到這一點 - 力從另一個子組件重新渲染的孩子嗎?

非常感謝您的任何建議。

編輯:這裏是代碼SummaryBanner組件:

import * as React from 'react'; 
import { Link, NavLink } from 'react-router-dom'; 
import { connect } from 'react-redux'; 
import { ApplicationState } from '../store'; 
import * as GlobalStore from '../store/GlobalVariables'; 

interface FetchDataExampleState { 
    collections: CollectionOfQuestions[]; 
} 

type SummaryBannerProps = 
    GlobalStore.GlobalState; 

class SummaryBanner extends React.Component<SummaryBannerProps, FetchDataExampleState> { 
    constructor(props: SummaryBannerProps) { 
     super(props); 
     this.state = { collections: [] }; 

     if (this.props.sessionId !== '' && this.props.sessionId !== undefined) { 
      fetch(this.props.clientSessionURL + '/' + this.props.sessionId + '/actions/get_main_collections', { method: 'POST', headers: { 'Accept': 'application/json' } }) 
       .then(response => response.json() as Promise<CollectionOfQuestions[]>) 
       .then(data => { 
        this.setState({ collections: data }); 
       }); 
     } 
    } 

    public render() { 
     return <ul className="nav metismenu summary-banner" id="side-menu" ref="menu"> 
      <li className="nav-header"> 
       <div className="dropdown profile-element"> <span> 
       </span> 
        <a data-toggle="dropdown" className="dropdown-toggle" href="#"> 
         <span className="clear"> <span className="block m-t-xs"> <strong className="font-bold summary-banner-header">Summary</strong> 
         </span></span> </a> 
       </div> 
      </li> 

      {(this.state.collections === null || this.state.collections.length === 0) ? (<li>No collection available</li>) : 
       (
        this.state.collections.map((collection, nodeIndex) => { 
         return <li key={collection.id}> {/* Separate collection */} 
          <NavLink to={'/questions/' + collection.id} activeClassName='fa fa-th-large'> 
           <span className="nav-label summary-banner-label">{collection.name}</span> 
          </NavLink> 
         </li> 
        })) 
      } 
     </ul>; 
    } 
} 

interface CollectionOfQuestions { 
    name: string; 
    description: string; 
    type: string; 
    id: string; 
    orderInSession: number; 
    totalNumberOfCollections: number; 
    nodes: CollectionOfNodes[]; 
} 

interface CollectionOfNodes { 
    code: string; 
    name: string; 
    description: string; 
    hasAdditionalQuestion: boolean; 
    type: string; 
    id: string; 
    questions: Question[]; 
} 

interface Question { 
    name: string; 
    text: string; 
    description: string; 
    productCore: string; 
    type: string; 
    answers: Answer[]; 
    possibleAnswers: string[]; 
    id: string; 
} 

interface Answer { 
    text: string; 
} 

export default connect(
    (state: ApplicationState) => state.globalVariables, 
    GlobalStore.actionCreators 
)(SummaryBanner) as typeof SummaryBanner; 
+0

對於SummaryBanner重新渲染,必須有某種狀態或道具裏面更改爲組件。您可以請添加來自SummaryBanner的代碼嗎?你如何改變你在SummaryBanner中顯示的數據? – bennygenel

+0

@bennygenel我編輯了我的問題。非常感謝您的迴應! –

+0

在獲取將返回已調用的'render'方法時,不要在構造函數中使用像提取那樣的異步操作。在'componentDidMount'生命週期方法中執行此操作 –

回答

0

下面是我想到的第一解決方案:

保持collections狀態Layout成分,把它作爲一個道具到SummaryBanner。然後使用React.cloneElement()LayoutonSubmit道具傳遞給嚮導,就像這樣:

<div className='col-sm-9'> 
    {React.cloneElement(React.Children.only(this.props.children), { 
    onSubmit: this._onSubmit, 
    })} 
</div> 

從電話的形式_onSubmit道具和實施Layout_onSubmit,使其更新collections狀態。

+0

的響應非常感謝,我想實現這種方式,但屬性不傳遞到孩子:''

{React.Children.map(this.props.children, (child => React.cloneElement(React.Children.only(child), { something: this.props.sessionId })))}
物業_something_具有價值的父母,但孩子是空 –

+0

我不明白爲什麼這是行不通的。您是否嘗試通過更改'this.props來進行測試。sessionId'到一些靜態字符串像''test「'看看它是否適用於兒童?我用類似的設置(在codepen中)(https://codesandbox.io/s/7z667w28jq)做了一個小測試用例,它可以工作,也許你可以用它作爲參考,看看你可能做錯了什麼? –

0

在從服務器返回提取時,調用render方法時,請勿在constructor內使用提取或任何異步操作。
您可以使用生命週期法componentDidMountDOCS
移動從構造此代碼:

componentDidMount(){ 
if (this.props.sessionId !== '' && this.props.sessionId !== undefined) { 
      fetch(this.props.clientSessionURL + '/' + this.props.sessionId + '/actions/get_main_collections', { method: 'POST', headers: { 'Accept': 'application/json' } }) 
       .then(response => response.json() as Promise<CollectionOfQuestions[]>) 
       .then(data => { 
        this.setState({ collections: data }); 
       }); 
     } 
}