最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to use Axios with asyncawait syntax in react? - Stack Overflow

programmeradmin0浏览0评论

I want to retrieve an array from my db using axios and display it in react ponent. I have used ponentDidMount() lifecycle method with async/await syntax as follows:

state = {
      products: []
}

async ponentDidMount() {
     const res=  await axios.get()
     .then(res => this.setState({products: res.data.products})
     .catch(err => console.log(err));
}

The return statement of the class ponent is as follows:

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

When I run this, it works fine, the state is updated and I can see all products in it but it seems that because every time the state updates, the ponents re renders itself and my element alignment on the web page is pletely disturbed.

I want the the request to wait until all elements are fetched from db and then map it on the state only once. Can somebody tell me how to achieve this?

When I hard code all 14 items of the array in state, I can the desired aligned carousel view as follows:

But when I fetch data from backend using axios in the same map function, everything gets disturbed.

Can anyone why is this happning?

I want to retrieve an array from my db using axios and display it in react ponent. I have used ponentDidMount() lifecycle method with async/await syntax as follows:

state = {
      products: []
}

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

The return statement of the class ponent is as follows:

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

When I run this, it works fine, the state is updated and I can see all products in it but it seems that because every time the state updates, the ponents re renders itself and my element alignment on the web page is pletely disturbed.

I want the the request to wait until all elements are fetched from db and then map it on the state only once. Can somebody tell me how to achieve this?

When I hard code all 14 items of the array in state, I can the desired aligned carousel view as follows:

But when I fetch data from backend using axios in the same map function, everything gets disturbed.

Can anyone why is this happning?

Share Improve this question edited May 4, 2020 at 23:05 Emma asked May 4, 2020 at 22:30 EmmaEmma 3271 gold badge6 silver badges14 bronze badges 5
  • Hi Emma, Can you put it on Codesandbox or Github where we can see the actual code? – Anurag Bhagsain Commented May 4, 2020 at 22:35
  • When you hardcoded the results, did you use the same json data, and did you set the state using this.setState in ponentDidMount? – Garrett Motzner Commented May 4, 2020 at 22:42
  • Yes the same JSON data, I used postman to run the api and then pasted the array result from there directly into the state of the element. So i didn't need setState at that time – Emma Commented May 4, 2020 at 23:08
  • Ok, I think I understand the problem now. I updated my answer. – Garrett Motzner Commented May 5, 2020 at 16:14
  • And had you still used setState, you might have noticed the same issue :). It helps to only change one thing at a time when debugging, but I probably would have done the same thing :D. – Garrett Motzner Commented May 6, 2020 at 20:15
Add a ment  | 

3 Answers 3

Reset to default 5

So for the example you gave, await (and also the assignment to res) is unnecessary if you are still using .then and .catch. If you wanted to use await, the more idiomatic way would be like this:

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

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

As to why it is causing rendering issues, well, that's because owl carousel is not patible with react without some work. When you initialize owl carousel, it changes the DOM as it needs, which means it takes your html and modifies it quite a bit - from something like this:

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

to something like:

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

But then react runs an update, looks at the DOM, and says "that's not right, let me fix that" and it then sets it back to what you originally had, which removes all the work owl carousel does. So all your divs will just be normal divs stacked on top of each other, not inside the carousel. So to fix this, I'd remend using either a carousel designed for react, or the react owl carousel package.

You should either use

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

or

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

When you use await keyword, you should think of it as a synchronous operation, thus you don't need no callbacks.

UPD: It seems like you have a typo, you should assign it like that

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

There's also typo in this.state.products.map

You can call function in ponentDidMount which call the api for you

ponentDidMount() { 
  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/entercode hereapi/public/home-product");
    if(res) this.setState({products: res.data.products})
    }catch(err){
       err => console.log(err)
    }
}
发布评论

评论列表(0)

  1. 暂无评论