React:如何在将“this.state.x”用于函数之前等待数据?

IT技术 javascript reactjs asynchronous
2021-04-09 21:10:08

我目前正在学习 React,有些东西对于新手来说并不那么容易......

我有一个简单的组件renders(请注意,li由于functiongetSlots,它呈现了一个数组):

render () {
    return (
        <ul>
          {this.getSlots(this.state.viewing).map(item => <li key={item}>{item}</li>)}
        </ul>
    )
  }

功能getSlots是:

constructor (props) {...}

getSlots (viewing) {

    SOME STUFF...

    const monday = this.state.house.monday

    return SOME STUFF...
  }

componentDidMount () {...}

render () {...}

关键是getSlots需要获取数据componendDidMount才能工作。实际上,此时,getSlots它不起作用(崩溃),因为它在获取数据之前运行(this.state.house.monday运行时为“空”)。

如何在运行之前等待数据被获取getSlots谢谢你的线索。

3个回答

您将需要有条件地渲染。在异步所需数据之前提供要加载的加载状态。您将需要类似以下内容:

class WrapperComponent extends PureComponent {
    constructor(props) {
        super(props);

        this.state = {
            isLoaded: false,
            data: null
        };
    }

    componentDidMount() {
        MyApiCall.then(
            res => this.setState({
                // using spread operator, you will need transform-object-rest-spread from babel or
                // another transpiler to use this
                ...this.state, // spreading in state for future proofing
                isLoaded: true,
                data: res.data
            })
        );
    }

    render() {
        const { isLoaded, data } = this.state;
        return (
            {
                isLoaded ?
                    <PresentaionComponentThatRequiresAsyncData data={ data } /> :
                    <LoadingSpinner /> // or whatever loading state you want, could be null
            }
        );
    }
}
我想我明白了,它有效。在我的路线中:<Route path='/schedule' render={() => (<Schedule {...this.state} />)} />以及在我的Schedule组件中,您解释的条件渲染: {this.props.areSlotsReady && this.getSlots(this.props.viewing).map(item => <li key={item}>{item}</li>)}谢谢。
2021-05-24 21:10:08
我知道已经晚了,但我有一个简短的问题。每次都调用 render() 吗?我以为它一开始只调用了一次。我只是好奇这个方法是如何工作的
2021-06-04 21:10:08
@KyleRichardson 如果需要完成多个 Api 调用并且需要等到所有调用都加载完毕怎么办?
2021-06-08 21:10:08
任何时候异步加载数据时,都需要提供预加载状态和加载后状态。条件渲染是你的朋友!如果您需要更明确的说明,请告诉我。
2021-06-12 21:10:08
它就像一个魅力。@Maxim Saenko 的解决方案也有效。还有一个与此相关的问题,但使用react router. 我有一条这样的路线<Route path='/schedule' render={() => (<Schedule {...this.state} otherData='just a test' />)} />如您所见,我通过了 mystate和 some otherData我在成功的Schedule组件以获得otherDatathis.props.otherData我还可以stuff从我的state但不是首先需要从数据库中获取的那些中检索一些我如何再次等待这些数据?
2021-06-15 21:10:08
constructor() {
  super()
  this.state = { isLoading: true }
}

componentDidMount() {
  ('fetch data').then(() => { this.setState({ isLoading: false }); })
}

render() {
  return (
    <div>
      {!this.state.isLoading && ('your code')}
    </div>
  );
}

类似的东西。

您可以在获取之前使用空数据初始化状态,constructor就像这样

constructor(){
 ....,
 this.state = { house: null}
}

并在getSlots方法中放置一个条件来检查是否已获取数据

getSlots (viewing) {

    if (!this.state.house) {
       return [];
    }

    SOME STUFF...

    const monday = this.state.house.monday

    return SOME STUFF...
  }

当数据到达时,只需像这样设置相应的状态

componentDidMount(){
   fetch().then((houses) => {
      this.setState({ houses: houses })
   })
}