ReactJS。在另一个组件中单击时渲染组件(基于类切换)

时间:2015-08-26 11:13:01

标签: jquery ajax reactjs

我需要在另一个组件中单击渲染组件,如下所示:

我有DevStatus组件,它只是两个bootstrap radiobuttons。我有IssuesList组件是boostrap列表。

codepen codefull page view

因此,当用户点击其中一个单选按钮时,我需要使用IssuesList单选按钮的closed_issues数组Closed Issues数组来呈现open_issues组件。Open Issues } {array} for IssuesList radiobutton)。我是React的新手,但我想我只是要改变组件的状态,它会触发重新渲染,这是正确的吗?

但是,我无法将DevStatus的状态与closed_issues上的点击事件相关联。你可以帮我这么做吗?

此外,那些open_issues$.getJSON数组实际上是来自function _getIssues() { let issues = $.getJSON('https://api.github.com/repos/org_name/project/issues?state=all&filter=all') .done( (data) => { issues = data } ); return issues; } 方法的jQuery ajax响应。如何实现此数据获取过程,以便它不会阻止UI线程,并且实际上在收到JSON响应时会呈现?

这就是我要获得JSON的方式:

_getIssues()

所以,我只会得到一个所有问题的数组,之后我需要把它分成两部分。但要做到这一点,我首先需要调用undefined方法,该方法首先返回undefined的数组,并在几毫秒之后该数组将成为有效数据。但是,我认为这足以打破app并且React不会呈现class DevStatus extends React.Component { constructor(props) { super(props); this.state = { issues: [{title: '', html_url: '#', state: 'open'}] }; this.CLOSED_ISSUE_ID = 'closed_issue_r'; this.OPEN_ISSUE_ID = 'open_issue_r'; } getIssues(p_url, p_data, cbSuccess) { console.log('getIssues'); let request = $.ajax({ url: p_url, method: "GET", data: p_data }); request.done(cbSuccess); request.fail(console.log); } componentWillMount() { let url = 'https://api.github.com/repos/repo/project/issues?state=all&filter=all'; this.getIssues(url, {issues: 'open'}, this.onBackendResponse.bind(this)); } onBackendResponse(data) { console.log('onBackendResponse'); this.issues = data; this.setState({ issues: data }); } onChangeRadioButton(e) { console.log('onChangeRadioButton') console.log(e.target.id); switch(e.target.id) { case OPEN_ISSUE_ID: this.setState({ issues: this.getOpenedIssues(this.issues).bind(this) }); break; case CLOSED_ISSUE_ID: this.setState({ issues: this.getClosedIssues(this.issues).bind(this) }); break; } } getClosedIssues(issues) { console.log('filter closed'); return issues.filter((issue) => { issue.state === 'open' }); } getOpenedIssues(issues) { console.log('filter opened'); return issues.filter((issue) => { issue.state === 'closed' }); } render() { console.log(this.issues); return ( <div className="dev-status-page col-centered"> <div className="issues col-centered"> <div className="btn-group" data-toggle="buttons"> <label className="btn btn-primary active"> <input type="radio" name="options" id={this.CLOSED_ISSUE_ID} autoComplete="off" onChange={this.onChangeRadioButton.bind(this)}/> Closed Issues </label> <label className="btn btn-primary"> <input type="radio" name="options" id={this.OPEN_ISSUE_ID} autoComplete="off" onChange={this.onChangeRadioButton.bind(this)} /> Open Issues </label> </div> <IssuesList issues={this.state.issues} /> </div> </div> ) } } class IssuesList extends React.Component { constructor(props) { super(props); } render () { let issues = this.props.issues.map( (item, index) => { return ( <a key={index} className="list-group-item" href={item.html_url} target="_blank"> {item.title} </a> ); }); return ( <div className="list-group"> {issues} </div> ); } } IssuesList.propTypes = { issues: React.PropTypes.array }; 的数组。如果这个假设是正确的,我该如何避免呢?

更新

现在我有了这个:

 if (sizeof($video_url)!=0) {

    echo 'true';

    }
        else
    {

    echo 'false';

    }

2 个答案:

答案 0 :(得分:1)

回答你的第一个问题:是的改变状态正是你应该做的。使用this.setState更改状态会再次调用render方法。

你可以这样做:

var CLOSED_ISSUE_ID = 'closed_issue_r', OPEN_ISSUE_ID = 'open_issue_r';
var getAsyncDataFromBackend = function(p_url, p_data, cbSuccess){
  var request = $.ajax({
                   url: p_url,
                   method: "POST",
                   data: p_data
                });
      request.done(cbSuccess);
}
//..
getInitialState:function(){
  //empty state so App doesnt <quote>break</quote>
  return {issue_data:[]}
},
componentWillMount:function(){
  //init component with open issues
  //will be executed emediately before render.
  getAsyncDataFromBackend(url, {issues: 'open'}, this.onBackendResponse);
},
render:function(){
  return (
    <button id={OPEN_ISSUE_ID} onClick={this.onChangeRadioButton}>opened</button>
    <button id={CLOSED_ISSUE_ID} onClick={this.onChangeRadioButton}>closed</button>
    <IssueList list={this.state.issue_data} />
  )
},
onChangeRadioButton: function(e){
  switch(e.target.id){
    case OPEN_ISSUE_ID:
      getAsyncDataFromBackend(url, {issues: 'open'}, this.onBackendResponse);
      break;
    case CLOSED_ISSUE_ID:
      getAsyncDataFromBackend(url, {issues: 'closed'}, this.onBackendResponse);
      break;
  }
},
onBackendResponse(data){
  this.setState({issue_data: data});
}
//...

在您的方法getAsyncDataFromBackend中,您很可能会封装一些ajax代码。

因此,您在react组件的render函数中所做的只是调用<IssueList list={this.state.issue_data} />组件。

我希望这有帮助吗?

EDIT2:我为AJAX和渲染部分做了一些代码示例,使其更加明显。

希望你现在能抓住我。

答案 1 :(得分:1)

最理智的解决方案是在保持反应并且不做助焊剂或状态容器的同时,将数据一直传递到第一个共同父级,然后再次传递给消费组件

使用单选按钮将组件中的回调发送到组件,使用更改从ajax调用的完成回调中触发,然后父级可以更新其状态并使用新数据重新呈现子级。

编辑:随着更新将问题更改为另一个解决方案,这是关于在一个组件中状态/数据更改时如何在兄弟/父项中触发重新渲染。