开发者问题收集

如何在 React 中将 Axios 与 async/await 语法结合使用?

2020-05-04
6693

我想使用 axios 从我的数据库中检索一个数组并将其显示在 react 组件中。我使用了 componentDidMount() 生命周期方法和 async/await 语法,如下所示:

state = {
      products: []
}

async componentDidMount() {
     const res=  await axios.get(http://santacruz.clickysoft.net/api/public/home-product)
     .then(res => this.setState({products: res.data.products})
     .catch(err => console.log(err));
}

类组件的返回语句如下:

 return (
  <div className="wwd animated" data-animation="bounceInLeft">
    <div className="wwd-slider">
      <div className="container-fluid">
        <div className="row">
          <div className="col-md-12 nlrp">
            <div className="owl-carousel owl-theme">
              {
                this.state.product.map( product => 
                  <div className="item">
                  <img src="images/p-01.png" className="img-fluid" />
                  <div className="wwd-over">
                    <a href="#">{product.product_name}</a>
                      <p>{product.info}</p>
                  </div>
                </div>
                )}
              }
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
);

当我运行它时,它工作正常,状态已更新,我可以看到其中的所有产品,但似乎因为每次状态更新时,组件都会重新呈现自身,并且网页上的元素对齐完全被打乱。

我希望请求等到从数据库中获取所有元素,然后仅将其映射到状态上一次。有人能告诉我如何实现这个吗?

当我对状态中数组的所有 14 个项目进行硬编码时,我可以获得所需的对齐轮播视图,如下所示:

enter image description here

但是当我在同一个 map 函数中使用 axios 从后端获取数据时,一切都会受到干扰。

enter image description here

有人能知道为什么会这样吗?

3个回答

因此,对于您给出的示例,如果您仍在使用 .then.catch ,则 await(以及对 res 的分配)是不必要的。如果您想使用 await,更惯用的方式应该是这样的:

async componentDidMount() {
     try {
         const res = await axios.get(http://santacruz.clickysoft.net/api/public/home-product)

         this.setState({products: res.data.products})
     } catch(err) {
         console.log(err)
     }
}

至于为什么它会导致渲染问题,那是因为 owl carousel 如果不进行一些工作就与 react 不兼容。初始化 owl carousel 时,它会根据需要更改 DOM,这意味着它会获取您的 html 并对其进行大量修改 - 从类似这样的内容:

<div className="owl-carousel owl-theme">
   <div className="item">
                  …
   </div>
</div>

到类似这样的内容:

<div class="owl-carousel owl-theme owl-loaded owl-drag">
    <div class="owl-stage-outer"><div class="owl-stage" style="transform: translate3d(-1176px, 0px, 0px); transition: 0s; width: 4704px;">
             <div class="owl-item cloned" style="width: 186px; margin-right: 10px;"><div class="item">
              …
            </div></div>
            <div class="owl-item active" style="width: 186px; margin-right: 10px;"><div class="item">
              …
            </div></div>
            <div class="owl-item cloned" style="width: 186px; margin-right: 10px;"><div class="item">
              …
            </div></div>
        </div></div>
     <div class="owl-nav">…</div>
</div>

但随后 react 运行更新,查看 DOM,并说“这不对,让我修复它”,然后将其设置回您原来的状态,这将删除 owl carousel 所做的所有工作。因此,您的所有 div 都只是堆叠在一起的普通 div,而不是在轮播内。因此,为了解决这个问题,我建议使用专为 react 设计的轮播,或 react owl carousel 包

Garrett Motzner
2020-05-04

您应该使用

axios.get(...).then(...).catch(...)

const result = await axios.get(...)
this.setState({products: result.data.product})

当您使用 await 关键字时,您应该将其视为同步操作,因此您不需要回调。

UPD: 似乎您有一个拼写错误,您应该这样分配它

this.setState({products: result.data.product})

this.state.product s .map 中也有拼写错误

Alex Khristo
2020-05-04

您可以调用 componentDidMount 中的函数来为您调用 api

componentDidMount() { 
  this.callAxiosApi(); 
}

So, in this function call the api through axios using async/await 
if you get response then set the state, if not console the error simple is that
callAxiosApi = async () => {
 try{
    const res = await axios.get("http://santacruz.clickysoft.net/entercode hereapi/public/home-product");
    if(res) this.setState({products: res.data.products})
    }catch(err){
       err => console.log(err)
    }
}
Umair Malik
2020-05-05