异步调用后渲染路由

Render Route after asynchronous call

我正在构建我的第一个 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>

提前感谢您的帮助:)

尝试这样的事情:

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>
    );
  }
}
<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>

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

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

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