Home > Back-end >  How to get current state data immediately in react.js?
How to get current state data immediately in react.js?

Time:07-08

I am new in react.js. I am trying to call an API during the select option is selected. But here I can't get the updated value, always I am getting old state values. Can anyone help me?

function TicketsPage() {
  useEffect(() => {
    fetchTicketTypes();
    fetchItems();
  }, []);

  const [sortByKey, setSortByKey] = useState();
  const updateSortByKey = async (e) => {
    //here set the data from select option-------
    setSortByKey(e.target.value);
    //here filter API is called-----------------
    await fetchItemsFilter();
  };

  const fetchItemsFilter = async (e) => {
    //here getting old data of sortByKey----------------
    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        sort: [[sortByKey, sortByOrder]],
      }),
    };
    fetch(`${process.env.REACT_APP_BASE_URL}/api/ticket`, requestOptions)
      .then((res) => res.json())
      .then(
        (jsonResponse) => {
          setIsLoaded(true);
          setTickets(jsonResponse);
        },
        (error) => {
          setIsLoaded(true);
          setError(error);
        }
      );
  };

  return (
    <select
      onChange={updateSortByKey}
      className="form-select"
      aria-label="Default select example"
    >
      <option key="">select</option>
      <option key="_updated_at" value="_updated_at">
        last activity
      </option>
      <option key="status" value="status">
        status
      </option>
    </select>
  );
}

CodePudding user response:

You see old value because the new value will be available in next render. One might think of doing this with useEffect, but I would consider to do it without it. General recommendation is not to overuse useEffect:

You don’t need Effects to handle user events. For example, let’s say you want to send an /api/buy POST request and show a notification when the user buys a product. In the Buy button click event handler, you know exactly what happened. By the time an Effect runs, you don’t know what the user did (for example, which button was clicked). This is why you’ll usually handle user events in the corresponding event handlers.

Just pass that new value as argument when calling the function:

  const updateSortByKey = async (e) => {
    setSortByKey(e.target.value);
    await fetchItemsFilter(e.target.value); // --> added argument
  };

I see also there is some sortByOrder inside fetchItemsFilter, you might need to pass that too, depending on situation.


But sometimes it may make sense to put search inputs in useEffect dependency, for example when:

Search inputs are often prepopulated from the URL, and the user might navigate Back and Forward without touching the input.

More on that here.

CodePudding user response:

Edit: I came back to this post upon further reflection to suggest just passing in the value as an argument and Giorgi Moniava has it. That's probably the simplest solution (although useEffect is how you would get the state value "immediately" if something similar comes up in the future).

It's a pretty common problem that many people run into. When you set the state the new value gets put into a queue first and then updates on the next render. It looks like perhaps you were trying to get that render to occur by calling the async function. Instead you can try calling useEffect to trigger when the sortByKey state is changed. It would look like this:

useEffect(()=> {
fetchItemsFilter();
},[sortByKey])

If you don't want the API call to trigger on first render, you can always pass in an additional value into either your state variable or another state variable to check if the updateSortByKey has been triggered.

useEffect(()=> {
if (triggered) {
fetchItemsFilter();
}
},[sortByKey])
  • Related