0

I set state(id) on button click and i want to use that data(id) in that state, it just showing undefined in the first click

[State Initialization] const [id,setId] = useState("");

[Onclick of Button]

`render: (record) => (
                <div>
                    <Button
                        className="details-btn-approve"
                        onClick={()=>{
                                handleApprove(record)
                        }}
                    >
                        Approve
                    </Button>
)`

[useEffect and calling on click action]

`

useEffect(()=>{
    },[id]);
    const handleApprove = async (record) => {
        setId(record.ID);
        console.log(id);
}

`

i was expecting the id to be changing every time i click button

here is the complete Code `

import {useEffect, useState} from "react";
import {Button, Card, Input, Modal, Table} from "antd";
import axios from "axios";
import {endPoints} from "./ApiEndPoints";

function Approval() {
    const [isLoading, setIsLoading] = useState(false);
    const [dataSource, setDataSource] = useState([]);
    const [searchedText,setSearchedText] = useState("");

    const [id,setId] = useState("");

    useEffect(()=>{
        ViewUnApproved();
    },[setDataSource])

    const ViewUnApproved = async () =>{
        setIsLoading(true);
        const {data: response} = await axios.get(
            endPoints.pendingApprovalAsset
        );
        if (response["status"] === 100){
            setIsLoading(false)
            setDataSource(response["pending_approval"]);
        } else if(response["status"] === 104){
            console.log('no data ')
        }
    }

    useEffect(()=>{
    },[id])

    const handleApprove = async (record) => {
        setId(record.ID);

        const data = {
            ASSET_ID: id,
        }
        const {data: response } = await axios.post(
            endPoints.approve,
            data
        );
        if((response["status"] = 100)){
            setIsLoading(false);
            console.log(response.to_be_approved);
        }
    }
    console.log(id);

    const columns = [
        {
            title: "Asset",
            dataIndex: "DESCRIPTION",
            key: "name",
            filteredValue:[searchedText],
            onFilter:(value,record)=>{
                return String(record.DESCRIPTION)
                        .toLowerCase()
                        .includes(value.toLowerCase()) ||
                    String(record.TAG_NUMBER)
                        .toLowerCase()
                        .includes(value.toLowerCase()) ||
                    String(record.BUILDING_NAME)
                        .toLowerCase()
                        .includes(value.toLowerCase()) ||
                    String(record.STATUS)
                        .toLowerCase()
                        .includes(value.toLowerCase()) ||
                    String(record.CONDITION)
                        .toLowerCase()
                        .includes(value.toLowerCase())
            }
        },
        {
            title: "Tag",
            dataIndex: "TAG_NUMBER",
            key: "tag",
        },
        {
            title: "Location",
            dataIndex: "BUILDING_NAME",
            key: "location",
        },
        {
            title: "Status",
            dataIndex: "STATUS",
            key: "status",
        },
        {
            title: "Condition",
            dataIndex: "CONDITION",
            key: "condition",
        },
        {
            title: "Action",
            key: "",
            render: (record) => (
                <div>
                    <Button
                        className="details-btn-approve"
                        onClick={()=>{
                                handleApprove(record)
                        }}
                    >
                        Approve
                    </Button>
                    <Button
                        className="details-btn-reject"
                        id={record.ID}
                        type="danger"
                        onClick={() => {
                            //showModal(record);
                        }}
                    >
                        Reject
                    </Button>
                </div>
            ),
        },
    ];
    return (
        <>
            <Card
                title="LIST OF ASSETS TO BE APPROVED"
                bordered={false}
                className="table-card"
            >
                <Input.Search className='search-input'
                              placeholder ="Search here ..."
                              onSearch={(value)=>{
                                  setSearchedText(value)
                              }}
                              onChange = {(e)=>{
                                  setSearchedText(e.target.value)
                              }}
                />
                <Table
                    loading={isLoading}
                    columns={columns}
                    dataSource={dataSource}
                    pagination={{ pageSize: 10 }}

                />


            </Card>
        </>
    );
}
export default Approval; 

`

sanjawena
  • 3
  • 2

2 Answers2

0

Using console.log() inside your handleApprove() function won't display the last value of the ID. Indeed, setId() is an async function so console.log() can be called even if setId() is not done yet. Move your console.log() out of the function and it will display the last id.

Furthermore, you're using class component that are no longer recommended by React. Here is a proper typescript code example: sandbox. If you're not using Typescript, just get rid of all the types and it will be ok for basic JS.

In your example, you're using a <Button /> component. This usage means you should use a callback (doc here) to send the click event to the parent component. The called function should be a useCallback() function (doc here).

Raphael Escrig
  • 146
  • 2
  • 6
  • i have seen the the example code but in my case i in the very same button of approve i need to get an Id of the data in that particular row of a table and use that id in an API – sanjawena Nov 23 '22 at 09:52
  • Can you send a sandbox with all the code logic you want to apply ? I think you should solve and close this issue because what you are saying here is something else than "React useState not updating on click its just one step behind in updating state". – Raphael Escrig Nov 23 '22 at 09:55
  • have just edited the question with complete codes – sanjawena Nov 23 '22 at 09:58
0

Inside your handleApprove, method updating the state of id will only update it in the next rerender.This is usually fast enough if you need it somewhere else in the code (e.g. the code inside return()). However if you need it immediately in handleApprove you should use the value you've calculated.

    const handleApprove = async (record) => {
        const newId = record.ID;
        setId(newId);
        console.log(newId);
        //do whatever you want with newId
}

state updates cause a re-render as mentioned in this answer. However the state only has the new value after the re-render, whereas your console log gets called before that re-render happens. if you wanted to just do some logic with a value you already know when you are setting that state, then just use the value you know!

rymanso
  • 869
  • 1
  • 9
  • 21