2017-07-05 5 views
0

私は、サイドメニューを使用して動的に生成されたテーブルに表示されるデータベースの結果をフィルタリングする反応を起こそうとしているフロントエンドコンソールを持っています。次のようにReact.js単一の親を介して別々の子どもの間で小道具を渡す

コンポーネントの階層は次のとおりです。

App.js 
| 
|--SideMenu.js 
|--ResultsTable.js 

だから私は親が子コンポーネントで小道具へのアクセスを持っており、それはあまりにもその子に小道具を渡すことができるということを理解しています。私がしようとしているのは、親App.jsを介して結果テーブルに話すためにsidemenuを取得することです(子供が直接通信できるようにする方法がない限り)。そして、それに応じてテーブルを更新しますが、問題。フィルタまたはリセットボタン(SideMenu.js内)をクリックすると、ボタンがクリックされてから登録されるまでにボタンがクリックされる必要がある結果テーブルコンポーネントでは、小道具の持ち込みが遅れることがあります。私は解決が簡単だと確信していますが、これまでのところ私は逃げました。私はApp.jsが新しい小道具をResultTable.jsに戻しているときに問題が発生したと思うが、それを修正する方法は完全にはわからない。

ここSideMenu.js

export default class SideMenu extends React.Component{ 

    constructor(){ 
     super(); 

     this.state={ 

      serviceParam: '', 
      filterParam: '', 
      services: [], 
     } 

     this.handleServiceChoice = this.handleServiceChoice.bind(this); 
     this.handleSearch = this.handleSearch.bind(this); 
     this.getServices = this.getServices.bind(this); 
     this.handleReset = this.handleReset.bind(this); 

    } 

    componentWillMount(){ 

     this.getServices(); 
    } 

    getServices(){ 
     const _this =this; 
     let servicesData; 

     let url = "http://mydevsite.ie/cgi-bin/log-queries/api/services"; 

     fetch(url) 
      .then((resp) => resp.json()) 
      .then(function(data){ 

       servicesData = data; 

       console.log("servicesData"); 
       console.log(servicesData); 

       _this.setState({ 
        services: servicesData 
       }); 
      }); 
    } 

    handleReset(){ 
     this.setState({ 
      serviceParam: null, 
      filterParam: null, 
     }); 

     let dropdownArrow = document.createElement("i"); 
     dropdownArrow.setAttribute("class", "material-icons right"); 
     dropdownArrow.innerHTML = "keyboard_arrow_down"; 
     document.getElementById("serviceDisplay").innerHTML = "Services"; 
     document.getElementById("serviceDisplay").appendChild(dropdownArrow); 

     this.props.filterCallback(this.state.serviceParam); 
    } 

    handleSearch(){ 


     if(document.getElementById('search').value && this.state.serviceParam){ 
      let filterParam = "&search="+document.getElementById('search').value; 
      console.log('In child - search 1'); 
      console.log(filterParam); 

      let parentProps; 
      parentProps= this.state.serviceParam+filterParam; 
      this.props.filterCallback(parentProps); 
     } else if (document.getElementById('search').value){ 
      let filterParam = "?search="+document.getElementById('search').value; 
      console.log('In child - search 2'); 
      console.log(filterParam); 

      let parentProps; 
      parentProps=filterParam; 
      this.props.filterCallback(parentProps); 
     } else{ 
      let filterParam = this.state.serviceParam; 
      console.log('In child - search 3'); 
      console.log(filterParam); 

      let parentProps; 
      parentProps=filterParam; 
      this.props.filterCallback(parentProps); 
     } 



    } 

    handleServiceChoice(e){ 
     console.log('sidebar target id'); 
     console.log(e.target.id); 

     let serviceParam; 
     let dropdownArrow = document.createElement("i"); 
     dropdownArrow.setAttribute("class", "material-icons right"); 
     dropdownArrow.innerHTML = "keyboard_arrow_down"; 
     document.getElementById("serviceDisplay").innerHTML = e.target.id; 
     document.getElementById("serviceDisplay").appendChild(dropdownArrow); 

     serviceParam = '?service='+e.target.id ; 

     this.setState({ 
      serviceParam: serviceParam, 
     }); 

    } 

    render(){ 
     return(

      <ul className="side-nav fixed blue accent-1"> 
       <li className="logo"></li> 

       <li> 
        <a id="serviceDisplay" href="#" className="dropdown-button waves-effect" data-activates="services">Services<i className="material-icons right">keyboard_arrow_down</i></a> 

         <ul id="services" className="dropdown-content"> 
          {this.state.services.map((dropdown)=>{ 
           return(
            <li key={dropdown.service}> 
             <a id={dropdown.service} href="#" className="waves-effect" onClick={this.handleServiceChoice}>{dropdown.service}</a> 
            </li> 
           ); 
          })}     
         </ul> 

       </li> 

       <li className="bold"><a href="#">Supplier ID Search</a></li> 
       <li className="search"> 
        <div className="container center-align"> 
         <input id="search" type="text" placeholder="Enter ID here" className="validate blue accent-2"></input> 

         <button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleSearch}> 
          Filter 
          <i className="material-icons right">search</i> 
         </button> 
        </div> 
       </li> 
       <li > 
        <div className="container center-align"> 
         <button className="btn blue accent-2 waves-effect" type="submit" onClick={this.handleReset}> 
          Reset Logs 
          <i className="material-icons right">autorenew</i> 
         </button> 
        </div> 
       </li> 


      </ul> 
     ); 



    }; 
} 

そしてResultsTable.jsための私のコードです:

export default class ResultsTable extends React.Component{ 

    constructor(){ 
     super(); 
     this.state = { 
      logs: [], 
      xml: '', 
      render_xml: false, 
     } 

     this.ResultsTable = this.ResultsTable.bind(this); 
     this.handleRequestXML = this.handleRequestXML.bind(this); 
     this.handleResponseXML = this.handleResponseXML.bind(this); 
     this.returnToLogs = this.returnToLogs.bind(this); 
     this.renderTable = this.renderTable.bind(this); 
     this.renderXml = this.renderXml.bind(this); 
    } 

    componentWillMount(){ 
     console.log('Child - In componentWillMount!'); 
     this.ResultsTable(); 

    } 

    componentWillReceiveProps(){ 
     console.log('Child - In componentWillReceiveProps!'); 
     console.log(this.props.filter); 

     this.ResultsTable(); 
    } 

    returnToLogs(){ 
     this.setState({ 
      render_xml:false 
     }); 
    } 

    handleResponseXML(e){ 
     const _this =this; 

     _this.setState({ 
      render_xml: true, 
     }); 

     let id_param = '?_id='+e.target.id+'&type=response'; 
     let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param; 
     fetch(url) 
      .then((resp) => resp.json()) 
      .then(function(data){ 

       let xml = data; 

       console.log("xml"); 
       console.log(xml); 

       _this.setState({ 
        xml: xml, 
       }); 

      }); 
    } 

    handleRequestXML(e){ 
     const _this =this; 

     _this.setState({ 
      render_xml: true, 
     }); 


     let id_param = '?_id='+e.target.id+'&type=request'; 
     let url = "http://mydevsite.ie/cgi-bin/log-queries/api/xml"+id_param; 
     fetch(url) 
      .then((resp) => resp.json()) 
      .then(function(data){ 

       let xml = data; 

       console.log("xml"); 
       console.log(xml); 

       _this.setState({ 
        xml: xml, 
       }); 
      }); 
    } 

    ResultsTable(){ 
     console.log('Child - In ResultsTable!'); 
     console.log(this.props.filter); 

     const _this =this; 
     let logData; 

     let url = "http://mydevsite.ie/cgi-bin/log-queries/api/logs"; 



     if(this.props.filter){ 
      console.log('Child - Service Choice!'); 
      console.log(this.props.filter); 
      url +=this.props.filter; 
     } 

     fetch(url) 
      .then((resp) => resp.json()) 
      .then(function(data){ 

       logData = data; 

       console.log("logData"); 
       console.log(logData); 

       _this.setState({ 
        logs: logData 
       }); 
      }); 

    } 



    renderTable(){ 
     console.log('In renderTable!'); 
     return (

      <table className="highlight"> 
       <thead> 
        <tr> 
         <th>ID</th> 
         <th>Created</th> 
         <th>Last Changed</th> 
         <th>Service</th> 
         <th>Supplier Identifier</th> 
         <th>Request XML</th> 
         <th>Response XML</th> 
        </tr> 

       </thead> 
       <tbody> 
       {this.state.logs.map((log)=>{ 
        return(
         <tr key={log._id}> 
          <td>{log._id}</td> 
          <td>{log.created}</td> 
          <td>{log.last_changed}</td> 
          <td>{log.service}</td> 
          <td>{log.supplier_identifier}</td> 
          <td><a id={log._id} onClick={this.handleRequestXML} href='#'>Click for XML</a></td> 
          <td><a id={log._id} onClick={this.handleResponseXML} href='#'>Click for XML</a></td> 
         </tr> 
        ); 
       })} 

       </tbody> 


      </table> 


     ); 
    } 

    renderXml(){ 
     console.log("In renderXml"); 
     return(
      <div className="card-panel"> 
       {this.state.xml} 
       <hr/> 
       <a className="waves-effect btn blue accent-2" onClick={this.returnToLogs}>Back to logs</a> 
      </div> 

     ); 
    } 

    render(){ 
     if(this.state.render_xml){ 
      return this.renderXml(); 
     } else { 
      return this.renderTable(); 
     } 
    } 
} 

そしてここでは、親App.jsコンポーネント

export default class App extends React.Component{ 

    constructor(){ 
     super(); 
     this.state = { 
      filter: null, 
     } 

     this.handleFilterParam = this.handleFilterParam.bind(this); 
    } 

    handleFilterParam(filter){ 
     console.log('In parent - handleSearchParam'); 
     console.log(filter); 
     this.setState({ 
      filter: filter 
     }); 
    } 

    render(){ 
     console.log('In parent - render'); 
     console.log(this.state.filter); 

     return (
      <div className="row"> 

       <div className="col s4 l3"> 
        <SideMenu 
         filterCallback={this.handleFilterParam} 
        /> 
       </div> 
       <div className="col s12 l9"> 
        <Header /> 
        <ResultsTable filter={this.state.filter}/> 
       </div> 

      </div> 

     ); 
    } 
} 

です私はReactやES6にはまだまだ新機能なので、もしかしたら素人だと思ったら事前に謝ってください。

+0

ただ、アプリケーション内のコードを実行され、コンポーネントの小道具として、いくつかのコールバックを伝承コンポーネントを再レンダリングします。 – Angels

+0

@Angels私は彼がすでにやっていることだと思います。 OP、私は 'componentWillReceiveProps'を使ってフィルターの変更に基づいて結果を更新していますが、新しいコンポーネントを受け取る' componentWillUpdate'を使う必要があると思います。フィルターが変わるたびに、古い小道具でAPI呼び出しをしています – Sander

+0

@Angels今は分かりました。 SideMenuにコールバックがあり、App.jsが新しい小道具をResultsTableに戻すようにトリガーしますが、最初のボタンをクリックしたときにそれを取り上げて再レンダリングするようには見えません。それはあなたが意味することですか? –

答えて

0

誰かがこの疑問を抱いてこの質問を見ている場合に備えて、私は非常に単純な解決策を見つけました。私は以前このライフサイクルメソッドを使用していましたが、今までそれを理解していませんでした。

だから、私のResultsTableコンポーネントでは、私は新しい小道具のために「聞く」し、それに応じて更新するには、このコードを追加:

componentWillReceiveProps(nextProps) { 
     if(this.props != nextProps) { 
      this.props = nextProps; 
      this.handleResultsTable(); 
     } 
    }