mohsen bahrami
mohsen bahrami

Reputation: 1

I need to listen update phase (in life cycle) without constantly sending get requests in react JS

I am trying to write a program that communicates with the client frequently and I need to quickly notice the changes and read the result from the server. But this request is constantly being sent and loaded, even when the user is not interacting. And this causes the user's system to be occupied.

this is mu code:

const AdminDashboard = () => {
   const [filterShow, setFilterShow] = useState({ sort: "", read: "", flag: "", skip: 0, limit: 15 });
   const [adminItemList, setAdminItemList] = useState([]);
   const [searchParams, setSearchParams] = useSearchParams();

   async function changeItem(updateItem) {
      // update admin item state
      await axios.put("{...}/api/admin", { ... });
   }
   
   useEffect(() => {
      async function resultItem() {
         // get result(admin items)
         await axios.get(`{...}/api/admin?${searchParams.toString()}`)
            .then((res) => {
               setAdminItemList(res.data.data);
            }).catch((res) => {
               console.log(res)
            });
      }
      resultItem();
   })

   return (<>
      {adminItemList.map((ai, i) => {
         return (<div key={i}>
            <AdminItem item={ai} count={i} skip={filterShow.skip} res={changeItem} />
         </div>)
      })}
   </>);
}

I know that I can avoid resending the request by using "useEffect" and passing an empty array to its second input. But I need to listen the changes so I can't do that. How can i listening the changes and prevent repeated get requests???

Upvotes: 0

Views: 40

Answers (1)

mohsen bahrami
mohsen bahrami

Reputation: 1

The only solution I could find:

  1. I moved the function "resultItem" outside of useEffect. And I wrote useEffect with an empty array in the second entry. then call "resultItem" in useEffect.

  2. I gave this function "resultItem" an input to receive a query so that it can be flexible

  3. I called it wherever I needed it

Note: In async functions, I first put that function in the Promise and call the "resultItem" in then().

I will put all the written codes here:

const AdminDashboard = () => {
   const usePuCtx = useContext(PublicContext);
   const { lang, dir } = usePuCtx.language;

   // base state
   const [allAdminItem, setAllAdminItem] = useState(0);
   const [filterShow, setFilterShow] = useState({ sort: "", read: "", flag: "", skip: 0, limit: 3 });
   const [adminItemList, setAdminItemList] = useState([]);
   // validate for show this page
   const [isAdmin, setIsAdmin] = useState(false);

   const [searchParams, setSearchParams] = useSearchParams();

   async function setResalt(radioName, radioState) {
      // set setting on query for get result(admin items)
      let newFilter = { ...filterShow };
      newFilter[radioName] = radioState;
      const queryStr = queryString.stringify(newFilter);
      setSearchParams(queryStr);
      new Promise((res, rej) => { res(setFilterShow(newFilter)) })
         .then(() => resultItem(queryStr));
   }

   async function changeItem(updateItem) {
      // update admin item state (read & flag)
      await axios.put(usePuCtx.ip_address + "/api/admin",
         { _id: updateItem._id, read: updateItem.read, flag: updateItem.flag })
         .then(() => resultItem(searchParams));
   }

   function showSkipPage(numberPage) {
      const nextResult = numberPage * filterShow.limit
      setResalt("skip", nextResult)
   }

   async function resultItem(query) {
      // get result(admin items)
      await axios.get(usePuCtx.ip_address + `/api/admin?${query.toString()}`)
         .then((res) => {
            setIsAdmin(true);
            setAdminItemList(res.data.data);
         }).catch(() => {
            // if auth token is wrong
            window.location = "/not-found";
         });
      // get all admin item number
      await axios.get(usePuCtx.ip_address + "/api/admin?limit=0&skip=0&flag=&read=&sort=close")
         .then((res) => {
            setIsAdmin(true);
            setAllAdminItem(res.data.data.length);
         }).catch(() => {
            // if auth token is wrong
            window.location = "/not-found";
         });
   }

   useEffect(() => {
      resultItem(searchParams);
   }, []);

   return (!isAdmin ? "" : (<>
      <div className="container-fluid" dir={dir}>
         <div className="row m-4" dir="ltr">
            {/* radio buttons */}
            <RadioFilterButton name="read" id1="read-" id2="read-false" id3="read-true"
               inner1={txt.radio_filter_button_all[lang]} inner2={txt.radio_filter_button_read_no[lang]}
               inner3={txt.radio_filter_button_read[lang]} res={setResalt} />
            <RadioFilterButton name="flag" id1="flag-" id2="flag-false" id3="flag-true"
               inner1={txt.radio_filter_button_all[lang]} inner2={txt.radio_filter_button_flag_no[lang]}
               inner3={txt.radio_filter_button_flag[lang]} res={setResalt} />
            <RadioFilterButton name="sort" id1="sort-close" id2="sort-far"
               inner1={txt.radio_filter_button_close[lang]} inner2={txt.radio_filter_button_far[lang]}
               res={setResalt} />
         </div><hr />
         <div className="m-4" style={{ minHeight: "100vh" }}>
            {
               // show result(admin items)
               adminItemList.map((ai, i) => {
                  return (<div key={i}>
                     <AdminItem item={ai} count={i} skip={filterShow.skip} res={changeItem} />
                  </div>)
               })
            }
         </div>
         <div className="row justify-content-center mt-auto" dir="ltr">
            <PageinationTool countAll={allAdminItem} limitCard={filterShow.limit} skipNum={filterShow.skip} res={showSkipPage} />
         </div>
         <Footer />
      </div>
   </>));
}

Upvotes: 0

Related Questions