Home > Back-end >  How to set a state varibale for a dynamically rendered component in React
How to set a state varibale for a dynamically rendered component in React

Time:11-07

I have an array full of user data I'm mapping though to display its information, and I'd like to have a button for each watchlist that deletes that watchlist (the backend already works I tested the deleteWatchlist function with the string value of an existing watchlist). My problem is that I get the name of the watchlist I need after mapping through the first array.

How do I set the state of the watchlistName for each watchlist?

import axios from "axios";
import { useSession } from "next-auth/react";
import React, { useState } from "react";
import useSWR from "swr";
import CoinInUserProfile from "./CoinInUserProfile";
const fetcher = (...args) => fetch(...args).then((res) => res.json());

function WatchlistContainer() {
  const { data: session } = useSession();

  const { data: userData, userError } = useSWR(
    `http://localhost:5000/api/users/${session?.id}`,
    fetcher
  );
  const [watchlistName, setWatchlistName] = useState();

  const deleteWatchlist = async () => {
    try {
      const res = await axios({
        url: `http://localhost:5000/api/users/${session?.id}/deletewatchlist`,
        method: "PUT",
        data: {
          watchlistName: watchlistName,
        },
      });
    } catch (error) {
      console.log(error);
    }
  };
  if (userError) return <div>failed</div>;
  if (!userData) return <div>loading data...</div>;
  console.log(userData);

  return (
    <div className="flex flex-col">
      {userData.watchlists.map((i) => (
        <div key={i._id} className="flex flex-col bg-blue-200 m-1">
          <p className="text-2xl text-blue-600">{i.watchlistName}</p>
          <button type="button" onClick={deleteWatchlist}>
            delete
          </button>
          {i.coins[0].coin.map((coin) => {
            return (
              <div>
                {/* <p key={coin.coinID}>{coin.coinID}</p> */}
                <CoinInUserProfile
                  coinID={coin.coinID}
                  name={coin.name}
                  symbol={coin.symbol}
                  watchlistName={i.watchlistName}
                />
              </div>
            );
          })}
        </div>
      ))}
    </div>
  );
}

export default WatchlistContainer;

CodePudding user response:

You needn't use state for this in your dynamically rendered component on each iteration pass the current watchlist (i.watchlistName) into the function as a parameter. To do this update your code as follows:

NOTE: Also note that async functions in a syncronous context returns a promise.

deleteWatchList

 const deleteWatchlist = async (watchlistName) => {
    
    try {
      const res = await axios({
        url: `http://localhost:5000/api/users/${session?.id}/deletewatchlist`,
        method: "PUT",
        data: { watchlistName }, // variable name same as key name can be used this way
      });
    } catch (error) {
      console.log(error);
    }
  };

delete button

          <button type="button" onClick={()=>deleteWatchlist(i.watchlistName)}>
            delete
          </button>

If it so happens that react does not trigger a re-render on the axios API call response add the following code to the deleteWatchList function:

  const deleteWatchlist = async () => {
    try {
      const res = await axios({
        url: `http://localhost:5000/api/users/${session?.id}/deletewatchlist`,
        method: "PUT",
        data: {
          watchlistName: watchlistName,
        },
      });
      // Code to Add
      res.then(response=>{
         // pull the deleted watchlist in the backend from the selected `user.watchLists` object in the current session.
      })  
      // Code to Add
    } catch (error) {
      console.log(error);
    }
  };

Recommendation on Rest API endpoints

Rest API is a semantic model for very specific purposes, this is so that one endpoint represents a CRUD (Create, Retrieve, Update, Delete).

Instead of exposing the endpoint as http://localhost:5000/api/users/${session?.id}/deletewatchlist using a POST update your API to accept calls on the 'DELETE' method.

And update the endpoint to http://localhost:5000/api/userwahtchlist.

Make the session.id the cookie and retreive the cookie on the request object in your web api. (will be something like req.cookie if you are perhaps using express.

  • Related