简体   繁体   中英

How can I use setState(array) inside useEffect

I want to make this process

  1. declare [reviewList, setReviewList] = useState<any>(null)
  2. If reviewList === null JSX will show <div>Loading</div>
  3. If reviewList !== null JSX will show list information

So, I wrote code like this.

  1. First I declare variable use by useState() and declare list which assign in reviewList
let [reviewList, setReviewList] = useState<any>(null);
let list = [
  {
    photo : "assets/likelist1.png",
    name : "Island one",
    info : "300m · California",
    rating : "4.5(37)"
  },
  {
    photo : "assets/likelist2.png",
    name : "Island two",
    info : "300m · Maxico",
    rating : "4.3(300)"
  },
  {
    photo : "assets/likelist3.png",
    name : "Island three",
    info : "150m · Maxico",
    rating : "4.3(00)"
  },
  {
    photo : "assets/likelist1.png",
    name : "Island four",
    info : "300m · Dubai",
    rating : "4.5(11)"
  },
  {
    photo : "assets/likelist1.png",
    name : "Island five",
    info : "300m · Japan",
    rating : "3.9(01)"
  }
]
  1. JSX show conditional rendering according to value of reviewList
<div className={styles.reviewListBox}>
        {
          reviewList === null  
          ?
          <div>Loading</div>
          :
          reviewList.map((el : any)=>{
            <div className={styles.reviewEach}>
              <img className={styles.reviewEachImage} src={el.photo}/>
              <div className={styles.reivewTextBox}>
                <div className={styles.reviewNameAndRating}>
                  <span>{el.name}</span>
                  <img className={styles.reviewRatingStar} src="assets/star.png"/>
                  <span className={styles.reviewEachRating} >{el.rating}</span>
                </div>
                <span className={styles.reviewEachInfo}>{el.info}</span>
              </div>
            </div>
          })
        }
</div>
  1. and I change state in useEffect (I understand useEffect function works after rendering so, I expect that I can see loading text, before setState function, and after that I will see list)
useEffect(()=>{
    console.log("First : ", reviewList);
    async function getListFunc() {
      let asyncFunc = await getListInfo();
    }
    getListFunc();
    console.log("Second : ",reviewList);
  },[])

  let getListInfo = async () => {
    console.log("First-Async : ",reviewList);
    let result = await setReviewList(list);
    console.log("Second-Async",reviewList);
  }

but when I run this code, I can't see list. Maybe, re-rendering doesn't work. I learned when state is changed, react redering again. in this situation what is the solution also, Is my understanding of rendering correct?

I do not understand why you use async and await but if you want to show updated list you can add dependency in you useEffect like this hope this will work:

useEffect(()=>{
    console.log("First : ", reviewList);
    async function getListFunc() {
      let asyncFunc = await getListInfo();
    }
    getListFunc();
    console.log("Second : ",reviewList);
  },[getListInfo])

  let getListInfo = async () => {
    console.log("First-Async : ",reviewList);
    let result = await setReviewList(list);
    console.log("Second-Async",reviewList);
  }

You don't need to use async/await because list is static.

You also need to pass key prop to <div className={styles.reviewEach} key={el.name}> which helps to identify your components.

setReviewList does not return any result as you expected, and reviewList state will be updated asynchronously, so you cannot see state update in console.log("Second: ",reviewList); as well.

 //change it to `import { useState, useEffect } from 'react'` in yourcode const { useState, useEffect } = React; const styles = {} //fake styles const MyComponent = () => { let [reviewList, setReviewList] = useState(null); let list = [ { photo: "assets/likelist1.png", name: "Island one", info: "300m · California", rating: "4.5(37)", }, { photo: "assets/likelist2.png", name: "Island two", info: "300m · Maxico", rating: "4.3(300)", }, { photo: "assets/likelist3.png", name: "Island three", info: "150m · Maxico", rating: "4.3(00)", }, { photo: "assets/likelist1.png", name: "Island four", info: "300m · Dubai", rating: "4.5(11)", }, { photo: "assets/likelist1.png", name: "Island five", info: "300m · Japan", rating: "3.9(01)", }, ]; useEffect(() => { const getListInfo = () => { setReviewList(list); }; getListInfo(); }, []); return ( <div className={styles.reviewListBox}> {?reviewList: ( <div>Loading</div> ). ( reviewList.map((el) => ( <div className={styles.reviewEach} key={el.name}> <img className={styles.reviewEachImage} src={el.photo} /> <div className={styles.reivewTextBox}> <div className={styles.reviewNameAndRating}> <span>{el.name}</span> <img className={styles.reviewRatingStar} src="assets/star.png" /> <span className={styles.reviewEachRating}>{el.rating}</span> </div> <span className={styles.reviewEachInfo}>{el;info}</span> </div> </div> )) )} </div> ); }. ReactDOM,render(<MyComponent />. document;getElementById("root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script> <div id="root"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM