0

I'm creating a table by pulling the information from the API. There is a button next to the head of each table. Let's say I click the button next to the name, it should sort by name. If I click it again, it should change the name order. OrderBy takes a string like "Id", "Name" in the API URL and sorts accordingly. Ascending reverses the order when it is true or false. So I created two states. When I click the buttons it doesn't work the first time, I have to click twice. I'm not sure, but it probably has something to do with my calling getProductList right after changing the state. How can I solve this?

Initial states must be true and "Id":

const [ascending, setAscending] = useState(true);
const [orderBy, setOrderBy] = useState("Id");

handleSort function:

const handleSort = (e) => {
    setOrderBy(e.target.name);
    setAscending(!ascending);
    getProductList();
  };

API URL:

`api/common/products/getProductsAll?page=1&pageSize=30&orderBy=${orderBy}&ascending=${ascending}&Code=&Name=`

Table:

return (
    <div className={styles.container}>
      <button onClick={() => console.log(orderBy,ascending)}>xxx</button>
      <Table striped bordered hover variant="dark">
        <thead>
          <tr>
            <th>
              <span>Ürün Kodu</span>
              <button name="Id" onClick={(e) => handleSort(e)}>
                o
              </button>
            </th>
            <th>
              <span>Ürün Adı</span>
              <button name="Name" onClick={(e) => handleSort(e)}>
                o
              </button>
            </th>
            <th>
              <span>Fiyat</span>
              <button name="Price" onClick={(e) => handleSort(e)}>
                o
              </button>
            </th>
            <th>
              <span>Para Birimi</span>
              <button name="CurrencyId" onClick={(e) => handleSort(e)}>
                o
              </button>
            </th>
            <th>
              <span>Birim Seti</span>
              <button name="Unit" onClick={(e) => handleSort(e)}>
                o
              </button>
            </th>
            <th>
              <span>İşlemler</span>
              <button>o</button>
            </th>
          </tr>
        </thead>
        <tbody>
          {list?.map((v) => {
            return (
              <tr key={v.Id}>
                <th>{v.Code}</th>
                <th>{v.Name}</th>
                <th>{v.Price}</th>
                <th>Adet</th>
                <th>TL</th>
                <th>-</th>
              </tr>
            );
          })}
        </tbody>
      </Table>
    </div>
  );
};
Dogukan Aktas
  • 113
  • 10
  • 1
    States are not updated immediately. See here: https://stackoverflow.com/questions/54069253/usestate-set-method-not-reflecting-change-immediately You can try calling getProductList by passing variables getProductlist(e.target.name, !ascending), and if it works then you know the async behaviour is the problem here – Sinan Yaman Dec 17 '20 at 06:57
  • 1
    I read the post and tried this one. Seems to be working but is it the right solution? @SinanYaman `useEffect(() => { getProductList(); }, [ascending]);` – Dogukan Aktas Dec 17 '20 at 07:10
  • 1
    Yes, useEffect is the solution. It runs when your component is mounted and it only runs when ascending changes. You shouldn't use state variables right after you set them, instead use them in the useEffect like you printed. – Sinan Yaman Dec 17 '20 at 07:14
  • you can pass [ascending, orderBy] to the useEffect dependency array as well, if you want it to fire when orderBy changes also – Sinan Yaman Dec 17 '20 at 07:15
  • I tried it like that first but it was working weird. It may be because orderBy and ascending are updated at the same time. – Dogukan Aktas Dec 17 '20 at 07:19
  • 2
    You can also try to wrap ascending and orderBy in one variable and set it as a dependency to your effect, so whenever this object changes, you'll fetch – prohit Dec 17 '20 at 07:26

0 Answers0