【问题标题】:How to await setting to state before mapping array?如何在映射数组之前等待设置状态?
【发布时间】:2021-08-01 18:54:21
【问题描述】:

正在尝试映射我存储在数组中的一些数据(下面的屏幕截图),但我似乎无法访问它,因为它是异步加载的。我怎么能等待数据?有没有办法在渲染函数中做到这一点?

 render() {
         
        return (
          {this.state.serials.map((number) => {
    return number.s && number.s.length? 
    (
        <h2 > {number.s[0].a}</h2>
  ) : null
})}
        )
    }

这是我获取数据的 componentDidMount():

componentDidMount() 
        const uid = this.state.user.uid;
        const gatewayRef = db.ref(uid + '/gateways');
        gatewayRef.on('value', (gateways_nums) => {
            const serialsArr = [];
          gateways_nums.forEach((gateway_num) => {
            const serialRef = db.ref('gateways/' + gateway_num.val()['gateway'])
            const last_temps =[];
            serialRef.on('value', (serials)=>{ 
                const ser = []
                serials.forEach((serial)=>{
                    ser.push(serial.val()['serial'])
                })
                last_temps.push({a: gateway_num.val()['gateway'], b: ser})
            })
            serialsArr.push({s:last_temps})
          });
          this.setState({serials:serialsArr})
        });
      }

非常感谢任何帮助!

【问题讨论】:

  • 用空数组启动序列状态。

标签: javascript reactjs typescript react-native


【解决方案1】:

试试这个:

render() {
  if(!this.state.serials) {
    // Ideally you should draw some loading spinner here
    // to indicate that data is not ready yet. But for a quick
    // solution you can just draw nothing
    return null
  }

  // Also "return ({ this.state.serials.map() })" is not valid syntax
  // you either need to return just an array without using braces, or
  // use some JSX tag and put braces inside of it
  return (
    <div>
        {this.state.serials.map(serial => ...)}
    </div>
  )
}

用大括号说无效语法,你也可以这样做

return this.state.serials.map(serial => ...)

或者(更好)

return (
  <>
    {this.state.serials.map(serial => ...)}
  </>
)

如果您不希望数据周围有额外的 div

【讨论】:

  • 感谢您的回答,但是,这仍然没有解决它,因为 this.state.serial 似乎已加载,但它仍然没有映射任何东西。如果我写 JSON.stringify(this.state.serials) 数组是空的。
  • 这意味着在componentDidMount 中获取这个serials 数组的算法存在问题,请尝试调试它。我可能看到了问题:您创建serialsArr,然后为每个serialRef 设置一个onvalue 处理程序。请注意,这些处理程序将在一段时间后异步调用。但是在设置这些侦听器之后,您立即执行this.setState({serials})。因此尚未调用侦听器,尚未填充数组,但是您已经将其保存到状态中,这就是为什么 render 内部为空
  • 虽然我看到你同步推送{s:last_temps},所以它不应该是空的。这意味着gateway_nums 可能是空的,所以没有任何东西被推入数组。我不确定你使用什么技术来填充这个数组,但你必须自己调试它或提供更多关于它应该如何工作的细节。好像您从某个数据库中获取它,也许数据库是空的。或者forEach 也可能异步调用回调,所以推送发生在setState 之后。关键是,问题似乎出在这个算法上
【解决方案2】:

我设法通过稍微改变算法让它工作。使用此代码,无需等待数据:

    componentDidMount() {
    const uid = this.state.user.uid;
    const serialRef = db.ref(uid + '/gateways');

    serialRef.on('value', (serial_numbers) => {
      const serials = [];
      serial_numbers.forEach((serial_number) => {
        const za = serial_number.val()['gateway'];
        const last_temps = [];
        const tempRef = db.ref('gateways/' + za);
        tempRef.orderByChild("serial").on('value', (temps) => {
          const temparray = [];
          temps.forEach((temp) => {
            temparray.push(temp.val());
          })
          const last_temp = temparray;
          last_temps.push({ l: last_temp, za });
          this.setState({ last_temps: last_temps })
        })
        serials.push({ s: last_temps });
      });
      this.setState({ serials: serials });
    });
  }

【讨论】:

    猜你喜欢
    • 2021-03-06
    • 1970-01-01
    • 2022-11-29
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多