DEV Community

mthomas7503
mthomas7503

Posted on

use and Effect!

Good day if you are reading this. It has been a while since my last post and I am still in the middle of my Software Engineering program with Flatiron School. I have been working with the React library so far.

Between the use of JSX to code in what looks to be an HTML/JS hybrid and React's declarative nature, this has been by far one of my favorite parts of the program.

However, something I struggled with and had to troubleshoot multiple times for this most recent project is state and CRUD. The project that I happen to be working on is just a simple search engine that fetches to an external API for the search and, by selecting the card image, sends a POST or DELETE request to my local API. It's very simple but very effective and pretty user-friendly.

The issue I kept running into in the beginning is the asynchronous nature of all of these parts working together. Because state is asynchronous, when I set my state to an empty array to help my iteration methods recognize the array and continue running the code, like so:

const [userChoice, setUserChoice] = useState([])"
Enter fullscreen mode Exit fullscreen mode

When I finally went to update state, state would update with the empty array as the first item to go into my API and then proceed to add it without adding the item I wanted to add. I would have to double-click in order to add the item to the list in the other component. Furthermore, because state was reset to the blank array whenever the code was re-rendered, this would be a frequent issue. Couple that this useEffect that ends in setting state:

useEffect (() => {fetch(www.myapi.com/v1/cards)
.then(...)...
Enter fullscreen mode Exit fullscreen mode

and I just ended up with an API FULL of blank arrays and the needed data sprinkled throughout. I started troubleshooting the problem by console.log()'ing the values of my state variables at key points, like the final .then() or after the useEffect was run. However, none of that helped me clear up the issues. But in troubleshooting. I did find some order as to how state is updated. That plus some help from my mentor, helped me solve the issue.

I began to notice that if I had state set first, but then tried to change it through the setState function, the setState function run, making sure to set state in React first, then the useEffect would run last after everything rendered and run the fetch request to load everything from the requested API or delete what was needed. The key problem was that while state runs first, it still runs asynchronously to everything so the empty array was set to state first and when the event listener was run, it would run based on the current state first, pulling the empty array, then state would be changed, causing a re-render, the useEffect to run, and then the empty array to be set for state again. Recognizing that helped me see how all the arrays kept getting put in there.

The next step, which was to get rid of all the arrays, wasn't as easy. I still hadn't fully seen the issue until I thought about it from a different angle.

I figured rather than pulling the ENTIRE API selection from the external API, I would instead store the information I need to display on the page in the tags and pull it from there based on event information like so:

   <ul key={cardData.id}>
                <li>
                    <img id={cardData.id} onClick={handleRemoveCard} alt={`${cardData.cardName}`} src={`${cardData.cardImg}`} />
                    <p>Set: {cardData.set}</p>
                </li>
            </ul>
Enter fullscreen mode Exit fullscreen mode

By doing that and using related tags, I was able to both use that to make a RESTful API of my own as well as lower the amount of fetches to an external API. For this bit of code though, I did call from the state function from within the component itself rather than the nearest parent. Testing using it in either the child or the parent did not change the outcome of the onClick event.

In the end, this worked out better than I could have hoped and it made my page run a bit smoother. I did have to add some interesting conditionals to make sure that my CSS loaded properly, like:

className={userChoices.length < 3  ? "decklistholder" : "decklist"}
Enter fullscreen mode Exit fullscreen mode

However, that is a story for a different time.

I feel like I still have a lot to learn in React, but solving that issue was a bit of a first step because knowing something is asynchronous and knowing WHEN exactly it will run are two different things. However, I think I am on the right track.

Top comments (0)