2017-05-03 9 views
1

현재 내 ReactJS 앱을 빌드하는 데 문제가 있습니다. 각 "제품"또는 "아이"는 어디에ReactJS - 형제 간의 참조 전달

| item | => | item's first child | => | first child's first child | .. 
|  | => | item's second child | 

: 같이

[{ 
    _id: 123456, 
    ... 
    children: [ 
     { 
     _id: 568, 
     ... 
     children: [...] // and so on, recursively 
      }, 
     .... 
    ] 
}] 

이 아키텍처는 일부 "진화 트리"로 렌더링 할 필요가 :이 형식을 취 배열이 구성 요소 (EvolutionStep)이고 각 "=>"화살표는 다른 구성 요소입니다 (EvolutionArrow). 그래서 우리는 세 가지 구성 요소가 있습니다

Evolution Chain => parent component, that renders 
Evolution Step => containing the evolution props (name, etc) 
Evolution Arrow => linking one step to one of it's children. 

화살표 다음 진화 단계의 예에서 (렌더링 방향을 가리킬 필요가 진화, 항목 및 항목의 첫 번째 자식 사이의 첫 번째 화살표가 똑바로 가리 킵니다을하지만 경우 항목의 첫 번째 자녀의 위치는 {top: -20px}과 같습니다. 화살표가 조금 위쪽을 가리켜 야합니다.

이렇게하려면 각 Evolution Step이 렌더링 될 때 Evolution Chain의 함수를 호출하여 참조를 로컬 상태에 추가합니다. 각 Evolution 화살표는 렌더링 될 때 가리켜 야 할 진화 단계에 대한 참조를 전달합니다. 문제는 진화 화살표의 reference 소품은 항상 un입니다. 정의 ...

내가 올바르게 설명했는지 모르겠으니 여기 내 코드가 있습니다. Evolution Arrow 클래스에서 console.log (this.props.references)를 넣으면 항상 정의되지 않습니다.

미리 도움 주셔서 감사합니다.

import PropTypes from 'prop-types'; 
import React from 'react'; 

class EvolutionStep extends React.Component { 

    componentDidMount() { 
     this.props.mountCallable(this.props.step._id, this); 
    } 

    render() { 
     return (
      <div style={{width: this.props.width + "%"}} data-identifier={this.props.step._id}>step</div> 
     ); 
    }; 

} 

class EvolutionArrow extends React.Component { 

    render() { 
     console.log(this.props); 
     return (
      <div>arrow</div> 
     ); 
    } 
} 

const EvolutionChain = class EvolutionChain extends React.Component { 

    constructor(props) { 
     super(props); 

     this.processStack.bind(this); 
     this.stepDidMount.bind(this); 
     this.preRender.bind(this); 

     this.state = { 
      cols: 0, 
      chainData: [], 
      refs: {} 
     }; 
    } 

    componentDidMount() { 
     this.processStack(); 
    } 

    stepDidMount(step_id, element) { 
     let refs = this.state.refs; 

     if (undefined == typeof(refs[step_id])) { 
      refs[step_id] = element; 
      this.setState({refs: refs}); 
     } 
    } 

    processStack() { 
     if (null == this.props.chain) { 
      return null; 
     } 

     let stack = [this.props.chain.children[0]]; 
     let results = []; 

     while (stack.length > 0) { 
      const current = stack.pop(); 
      // build current element 
      results.push({type: 'step', props: {step: current} }); 
//   results.push(<EvolutionStep key={current._id} ref={(step) => this.addRef(current._id, step)} step={current} width={(100/this.state.cols)}/>); 
      this.setState({cols: this.state.cols + 1}); 
      if (current.children.length > 0) { 
       let arrows = []; 
       current.children.map((item) => { 
        arrows.push({pointsTo: item._id}); 
        //arrows.push(<EvolutionArrow pointsTo={item._id} references={this.state.refs}/>); 
       }); 
//    results.push(<div className="arrow" width={(100/this.state.cols)}>{arrows}</div>); 
       results.push({type: 'arrows', arrows: arrows}); 
       this.setState({cols: this.state.cols + 1}); 
       stack = current.children; 
      } 
     } 

     results.reverse(); 
     this.setState({chainData: results}); 
    } 

    preRender() { 
     var components = []; 
     this.state.chainData.map((item) => { 
      switch (item.type) { 
       case 'step': 
        components.push(<EvolutionStep key={item.props.step._id} {...item.props} mountCallable={(step_id, elem) => this.stepDidMount(step_id, elem)}/>); 
        break; 
       case 'arrows': 
        let arrows = []; 
        item.arrows.map((arrow) => { 
         arrows.push(<EvolutionArrow pointsTo={arrow.pointsTo} references={this.state.refs[arrow.pointsTo]} />); 
        }); 
        components.push(<div className="arrow">{arrows}</div>); 
        break; 
      } 
     }); 

     return components; 
    } 

    render() { 

     let toRender = this.preRender(); 
     return (
      <div className="container-fluid"> 
       {toRender} 
      </div> 
     ); 
    } 

}; 

/** TODO: PropTypes **/ 

export default EvolutionChain; 
+0

을 기반으로 그래서'stepDidMount' 호출 여부를지고있다? –

+0

'stepDidMount'가 실제로 호출되고 요소와 오른쪽'step_id'를 전달합니다. 모든 EvolutionArrow 구성 요소의'references' prop가'undefined '로 남아 있기 때문에 상태 업데이트가 자식에게 전달되지 않는 것 같습니다. – Lucio

답변

0

수정 됨! 내가해야 할 일을했을 모든

0

심판componentDidMount() 트릭을 할 ... 그렇지 않으면 조건이 항상 거짓, stepDidMount에서 따옴표로 undefined 포장입니다.

다음 코드는 두 형제 사이의 통신을 설정하는 데 도움이됩니다. 설정은 render() 및 componentDidMount() 호출 중에 부모에서 수행됩니다. 그것은 https://reactjs.org/docs/refs-and-the-dom.html

class App extends React.Component<IAppProps, IAppState> { 
    private _navigationPanel: NavigationPanel; 
    private _mapPanel: MapPanel; 

    constructor() { 
     super(); 
     this.state = {}; 
    } 

    // `componentDidMount()` is called by ReactJS after `render()` 
    componentDidMount() { 
     // Pass _mapPanel to _navigationPanel 
     // It will allow _navigationPanel to call _mapPanel directly 
     this._navigationPanel.setMapPanel(this._mapPanel); 
    } 

    render() { 
     return (
      <div id="appDiv" style={divStyle}> 
       // `ref=` helps to get reference to a child during rendering 
       <NavigationPanel ref={(child) => { this._navigationPanel = child; }} /> 
       <MapPanel ref={(child) => { this._mapPanel = child; }} /> 
      </div> 
     ); 
    } 
}