Home > Enterprise >  React js : executing functions dependent on state change
React js : executing functions dependent on state change

Time:08-31

I want to execute a function only after a state has been set.

My code is as below


export function Details() {

    let params = useParams();


     const certificateData = useContext(DataContext) //fetching data from the database on load
  
     const [individualData,setIndividualData] = useState([])
     const [tokenID,setTokenID] = useState('')

        
        const setIndividualDetails = async () => {
        
            setIndividualData(certificateData.find(uploadedFile => uploadedFile.QRurl === params.QRurl))    
        }
        

        useEffect(() => {
            const fetchTokenID = async () => {

                await setIndividualDetails()

                try{
                    const {data} = await axios({
                        method: "GET",
                        url: `https://api.nftport.xyz/v0/mints/${individualData.transaction_hash}?chain=polygon`,
                        headers: {
                            'Content-Type': 'application/json',
                            Authorization: '4d86xxxxxx-929e-xxxx'
                        }
                    });

                //   setTokenID(token_id)    
                    console.log(data.token_id) 

                }catch (error) {
                    console.log(error)
                }
            }

            fetchTokenID()
        
        },[certificateData])
   


  return (

    <div>
       {individualData && (<h2>{individualData.transaction_hash}</h2>)}
    </div>
)}


In the above code my axios call to the api requires the paramater individualData.transaction_hash which is undefined in the intitial render and throws the undefined error

My context (DataContext) that sets the value of certificateData gets its value only on the second render, meanwhile axiox request has been called on the first render

How do I ensure the axios request runs only after individualData has got its value? Please help

I tried a lot of async await but it does not seem to work.

Edit after answer changed my useEffect to below and took setIndividualDetails outside

  useEffect(() => {
                if (certificateData.length === 0) {
                   return;
                }
                
                setIndividualDetails()

                if (!individualData || individualData.length === 0) 
                    return;

                fetchTokenID()

             }, [certificateData, individualData]);

CodePudding user response:

Why not just condition it?

const fetchTokenID = async () => {
   ...
};

useEffect(() => {
   // Make sure `individualData` has members.
   if (individualData.length === 0) {
      return;
   }

   // If above condition is not met, run the function as intended.
   fetchTokenID();
}, [certificateData, individualData]);

Here we make the useEffect also "watch" the value of individualData by including it in the dependency array.
And then basically saying only run the useEffect contents if the individualData array contains values.

I'm assuming you'd want to run fetchTokenID only a single time, in which case we should also handle that, since this useEffect will run every time the value of individualData changes.

This can be handled either via useRef that would determine if the function has already ran.

Example:

const hasFetchedRef = useRef(false);

const fetchTokenID = async () => {
   ...
};

useEffect(() => {
   // Make sure the function doesn't run more than a single time.
   if (hasFetchedRef.current) {
      return;
   }
   // Make sure `individualData` is not `null`/`undefined` and that it has members.
   if (!individualData || individualData.length === 0) {
      return;
   }

   // If above conditions are not met, run the function as intended.
   fetchTokenID();
}, [certificateData, individualData]);

Alternatively, maybe we could rely on the value of tokenID if we set it in the fetchTokenID.

Example:

const fetchTokenID = async () => {
   ...
   setTokenID(someValue);
   ...
};

useEffect(() => {
   // Make sure the function doesn't run more than a single time.
   if (!tokenID) {
      return;
   }
   // Make sure `individualData` is not `null`/`undefined` and that it has members.
   if (!individualData || individualData.length === 0) {
      return;
   }

   // If above conditions are not met, run the function as intended.
   fetchTokenID();
}, [certificateData, individualData]);
  • Related