【问题标题】:How to use Axios with async/await syntax in react?如何在反应中使用带有 async/await 语法的 Axios?
【发布时间】:2020-08-19 11:56:43
【问题描述】:

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

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语句如下:

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

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

我希望请求等到从 db 中获取所有元素,然后仅将其映射到状态一次。有人可以告诉我如何实现这一目标吗?

当我在 state 中对数组的所有 14 项进行硬编码时,我可以得到所需的对齐轮播视图,如下所示:

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

谁能告诉我为什么会这样?

【问题讨论】:

  • 嗨,Emma,你能把它放在Codesandbox 或 Github 上,我们可以看到实际代码吗?
  • 硬编码结果时,是否使用了相同的json数据,是否在componentDidMount中使用this.setState设置状态?
  • 是的,同样的 JSON 数据,我使用 postman 运行 api,然后将数组结果从那里直接粘贴到元素的状态中。所以当时我不需要 setState
  • 好的,我想我现在明白问题所在了。我更新了我的答案。
  • 如果您仍然使用setState,您可能已经注意到同样的问题:)。在调试时一次只更改一件事会有所帮助,但我可能会做同样的事情:D。

标签: javascript reactjs


【解决方案1】:

你可以调用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)
    }
}

【讨论】:

  • 这个答案如果有解释会更好。
【解决方案2】:

因此,对于您给出的示例,如果您仍在使用 .then.catch,则无需等待(以及对 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 without some work。当您初始化 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 package

【讨论】:

  • 我也添加了组件的返回块,如果你能看一下并告诉我是否遗漏了什么。
  • 据我所知,一切看起来都很干净......在你的项目加载之前,你会得到一个空白的轮播,但它们应该像任何其他方式一样加载......另外,你没有在轮播中你的产品没有key,所以 react 会抱怨,因为它不知道要重复使用哪个组件。将 .item div 的键设置为唯一的产品标识符。
  • 要诊断问题,我们可能需要查看实际的页面,以便我们可以使用浏览器开发人员工具查看它。这可能是一个奇怪的 CSS 问题。
  • 哦,不,可能是 owl carousel 不适合 react。这是一个 jQuery 插件,所以它可能有反应问题...
【解决方案3】:

你应该使用

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

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

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

统一更新: 看来你有错字,你应该这样分配它

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

this.state.products.map

中也有错别字

【讨论】:

  • 我也试过了,但没用,这就是为什么我认为 promises 会起作用的原因
  • 如果你能得到承诺工作,那么async/await 也应该工作。它们实际上是处理 Promise 的两种不同方式。
  • 哦,好吧,我猜是返回块的问题。我也添加了组件的返回块,如果你能看一下并告诉我是否遗漏了什么。
猜你喜欢
  • 2017-11-20
  • 1970-01-01
  • 2018-12-26
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 2018-09-14
  • 1970-01-01
  • 2021-02-17
相关资源
最近更新 更多