3

我正在创建一个主从导航,就像这里的示例反应路由器示例一样;

我有一个容器组件OneCheckpointContainer,它呈现一个导航面板CheckpointNav(链接)和一个数据组件OneCheckpointData(这个家伙在加载时获取数据,并呈现OneCheckpointView.

当我单击其中的一个链接时CheckpointNav时,除了浏览器中的 URL 更改之外,什么都没有发生。直到我刷新页面才获取新数据,然后在子视图中呈现一个新组件。(也没有错误)

我不确定这个错误是否是因为子组件也负责获取数据以及视图。

这是我设置路线的方式:

  <Route path="/modules/:id" component={OneCheckpointContainer}>
    <Route path="/modules/:id/checkpoints/:cp_id" component={OneCheckpointData} />
  </Route>

OneCheckpointContainer

import React from 'react';
import CheckpointNav from './CheckpointNav';

class OneCheckpointContainer extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      checkpoints: null,
      user: null
    };

  }

  componentWillMount() {
    this.loadCheckpoints();
    this.context.getUser((data) => this.setState({ user: data }));
  }

  loadCheckpoints() {
    $.ajax({
      url: `/api/v1/modules/student/${this.props.params.id}/checkpoints`,
      method: 'GET',
    }).done((data) => {
      this.setState({ checkpoints: data });
    });
  }

  render() {
    return (
      <div>
        <div className="col-xs-3">
          <CheckpointNav mid={this.props.params.id} checkpoints={this.state.checkpoints} />
        </div>
        <div className="col-xs-9">
          { this.props.children || <div>No Children Yet</div>}
        </div>
      </div>
    )
  }
}

OneCheckpointContainer.displayName = OneCheckpointContainer;

OneCheckpointContainer.contextTypes = {
  getUser: React.PropTypes.func.isRequired
};

export default OneCheckpointContainer;

这是CheckpointNav虽然我不相信这个错误在这里:

import React from 'react';
import NavLink from '../widgets/NavLink';

const CheckpointNav = (props) => {
  const checkpointList = props.checkpoints && props.checkpoints.length > 0 ?
    props.checkpoints.map((item) => {
      return <li key={item.cp._id} className="list-group-item">
      <NavLink className="nav-link" to={"/modules/" + props.mid + "/checkpoints/" + item.cp._id}>
      { item.cp.title}</NavLink></li>
    }) : <div>No CPS</div>;
  return (
    <div className="card one-module-card">
      <div className="card-block modules-card-body">
        <ul className="list-group tags-group">
          { checkpointList }
          <li className="list-group-item new-cp"><NavLink className=""
            to={'/post/checkpoint/' + props.mid}
          >
            New Checkpoint
          </NavLink></li>
        </ul>
      </div>
    </div>
  );

};

export default CheckpointNav;

除非我刷新,否则OneCheckpointData 不会获取新数据并呈现新数据

import React from 'react';
import CheckpointView from './CheckpointView';

class OneCheckpointData extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      checkpoint: null,
      user: null
    };

  }

  componentWillMount() {
    this.loadCheckpoint();
    this.context.getUser((data) => this.setState({ user: data }));
  }

  loadCheckpoint() {
    $.ajax({
      url: `/api/v1/modules/three/cp/${this.props.params.cp_id}`,
      method: 'GET',
    }).done((data) => {
      this.setState({ checkpoint: data });
    });
  }

  render() {
    return this.state.checkpoint ? <CheckpointView user={this.state.user} checkpoint={this.state.checkpoint} /> : null;
  }
}

OneCheckpointData.displayName = OneCheckpointData;

OneCheckpointData.contextTypes = {
  getUser: React.PropTypes.func.isRequired
};

export default OneCheckpointData;

** 我忽略了 OneCheckpointView,因为它应该是无关紧要的 **

4

4 回答 4

6

在这种情况下,您可以获得道具作为函数的参数,您可以像下面一样 loadCheckpoing(props)发送新的道具componentWillReceiveProps

componentWillMount(this.props) {
  this.loadCheckpoint(this.props);
}

componentWillReceiveProps(nextprops) {
  this.loadCheckpoint(nextprops);
}

loadCheckpoint(props) {
  this.context.getUser((data) => this.setState({ user: data }));
  $.ajax({
    url: `/api/v1/modules/three/cp/${props.params.cp_id}`, //please check i have replace the this.props to props as we have props as a parameter
    method: 'GET',
  }).done((data) => {
    this.setState({ checkpoint: data });
  });
}

我更喜欢使用 react-redux 或回流库来处理您的 ajax 数据查询,但我提出的解决方案应该可以为您完成这项工作。

于 2016-08-22T20:31:37.390 回答
1

诊断的两个步骤:

  1. loadCheckpoint每次单击不同的链接时,检查您的方法是否已被调用。就像console.log(new Date().toLocaleTimeString())在那个方法中那样留下一行

  2. 如果步骤 1 成功,则检查这部分是否存在this参考问题: (data) => { this.setState({ checkpoint: data }); }

顺便说一句,您最好将 ajax 调用放入componentDidMount方法中。参考:https ://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount

于 2016-08-19T09:54:44.827 回答
1

我认为这是因为您在 componentwillMount 中调用了函数 loadcheckpoints。这在组件生命周期中只被调用一次。由于在您单击导航栏中的链接时组件已经安装,因此不会调用组件。因此,不会获取数据。

我想,您应该尝试以下方法。CheckpointNav 中链接的 onclick 函数应从 OneCheckpointContainer 传递。加载的数据应设置为容器中的状态,该容器会将数据作为 props 传递给 OneCheckpointData。

于 2016-08-17T13:17:17.560 回答
1

问题是您的组件仅在安装之前获取数据。这仅适用于它们第一次显示。这些组件还需要在收到新属性时获取它们的数据,例如导航到新位置后来自路由器的 id。

为此,最简单的方法是添加一个componentWillReceiveProps将先前的道具与新道具进行比较并在需要时获取新数据的方法。

另一种方法是onEnter在您的 Routes 配置中添加一个处理程序,以便在路由更改时获取数据。

检查此问题的答案以查看这两种方法的示例。

于 2016-08-17T13:15:06.307 回答