异步调用后渲染路由

时间:2017-07-13 14:51:37

标签: javascript reactjs react-router axios

我正在构建我的第一个React应用程序。我正在尝试从react-router-dom渲染一些路由。 从主要组件我调用我的api获取一个json对象,然后我更新状态。问题是我的子组件在设置新状态后没有重新渲染,因此我在子组件中没有道具。我使用了一些函数,如forcerender和componentWillReceiveProps,但仍然无法正常工作

我确定这不是一个大问题,但我一直试图解决这个问题几个小时,但我无法让它发挥作用。

这是我最近的尝试:

class DetectorEfficiencyCalculator extends Component {
  constructor(props) {
    super(props);
        this.state = {
        detectors: []
    };
        axios.get(`/detectors`)
      .then(res => {
        const detectors = res.data;
        this.setState({ detectors });
           console.log('state updated')
      });
  }



  render() {
    return (
      <div className="DetectorEfficiencyCalculator">
          <RoutesHandler detectors={this.state.detectors}/>
      </div>
    );
  }
}

class RoutesHandler extends Component{
    constructor(props) {
        super(props);
        this.state        = { detectors: props.detectors } ;
    }
    componentWillReceiveProps(nextProps) {
        this.setState({detectors:nextProps.detectors})
        this.forceUpdate()
    }
      render() {
      console.log('render')
    return (
      <div className="RoutesHandler">
          <Switch>
              <Route exact path='/frontend/Detectors' component={DetectorList} detectors={this.props.detectors}/>
              <Route  path='/frontend/Detectors/:number' component={DetectorDetail} detectors={this.props.detectors}/>
          </Switch>

      </div>
    );
  }

}



class DetectorList extends Component {

  render () {
        console.log('renderList')
      if (!this.props.detectors) {
          return null;
      }
    return (
      <ul>
          {this.props.detectors.map(u => {
              return (
                  <Detector
                      id={u.id}
                      name={u.name}
                      single={u.single}
                      threshold={u.threshold}
                      angle={u.angle}
                  />
              );
          })}
      </ul>
    );
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

提前感谢您的帮助:)

2 个答案:

答案 0 :(得分:0)

尝试这样的事情:

&#13;
&#13;
class DetectorEfficiencyCalculator extends Component {
  state={detectors:[]}

  componentDidMount(){
    const self = this;
    axios.get(`/detectors`) //do it here...
      .then(res => {
        const detectors = res.data;
        self.setState({ detectors });
           console.log('state updated')
      });
  }


  render() {
    return (
      <div className="DetectorEfficiencyCalculator">
          <RoutesHandler detectors={this.state.detectors}/>
      </div>
    );
  }
}

class RoutesHandler extends Component{       
   render() {
      console.log('render')
    return (
      <div className="RoutesHandler">
          <Switch>
              <Route exact path='/frontend/Detectors' component={DetectorList} detectors={this.props.detectors}/>
              <Route  path='/frontend/Detectors/:number' component={DetectorDetail} detectors={this.props.detectors}/>
          </Switch>

      </div>
    );
  }

}



class DetectorList extends Component {

  render () {
        console.log('renderList')
      if (!this.props.detectors) {
          return null;
      }
    return (
      <ul>
          {this.props.detectors.map(u => {
              return (
                  <Detector
                      id={u.id}
                      name={u.name}
                      single={u.single}
                      threshold={u.threshold}
                      angle={u.angle}
                  />
              );
          })}
      </ul>
    );
  }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
&#13;
&#13;

基本上,您不希望在构造函数中执行任何ajax调用或db访问,这不是在React中执行此操作的正确方法,因为可以多次调用构造函数。而是使用React组件生命周期方法componentDidMount来启动api调用。另外我使用变量(self)来保存对组件的引用(this),这样我就可以在axios promise处理程序中使用它。

答案 1 :(得分:0)

好的,我进入了解决方案:路由渲染了一个函数,我在其中渲染组件并使用我需要的道具加载它。

        this.RenderDetectorDetail = (props) => {
            return (
                <DetectorDetail detectors={this.props.detectors}/>
            );
    };
    
     <Route  exact path='/frontend/Detectors' render={this.RenderDetectorList} />