Problems adding attributes when maping arrays

Viewed 73

I am trying within the changeEventStatus function to add an isJoined attribute to true or false, depending on whether the user is already in that event or not. What I have thought of doing so far is to first filter between 2 arrays and then go through and compare the element of the original array versus the element of the filtered array using a condition.

The problem is that while the conditional works, it only takes 1 element as true and adds the attribute as true leaving all other elements in the array as false. In the filtered array there are 2 objects so it should return an array with 2 true elements within its attributes.

// React
import React, { useEffect, useState } from "react";

// Chakra-ui
import {
  SimpleGrid,
  Box,
  Center,
  Text,
  Stack,
  Button,
  Spinner,
  Flex,
  useToast,
} from "@chakra-ui/react";

// Supabase
import { supabase } from "../../client";

const EventCard = () => {
  const toast = useToast();
  const [events, setEvents] = useState([]);
  const [isJoining, setIsJoining] = useState(false);
  const [eventId, setEventId] = useState(null);

  useEffect(() => {
    getEvents();
    changeEventStatus();
  }, []);

  const getEvents = async () => {
    const { data, error } = await supabase.from("events").select("*");
    setEvents([...events, ...data]);
  };

  const toaster = () => {
    return toast({
      title: "¡Event Message!",
      description: "You already participate in this event.",
      status: "error",
      duration: 3000,
      isClosable: true,
    });
  };

  const isUserParticipateInEvent = async (userId, eventId) => {
    let { data: event_participants, error } = await supabase
      .from("event_participants")
      .select("*")
      .eq("participant_id", userId)
      .eq("event_id", eventId);
    if (event_participants.length > 0) {
      return true;
    } else {
      return false;
    }
  };

  const joinToEvent = async (id) => {
    const user = supabase.auth.user();
    let userId = user.id;
    let eventId = Number(id);

    setEventId(id);

    const participant = {
      participant_id: userId,
      event_id: eventId,
    };

    let isParticipating = await isUserParticipateInEvent(userId, eventId);

    if (!isParticipating) {
      try {
        setIsJoining(true);
        const { data, error } = await supabase
          .from("event_participants")
          .insert([participant]);
        if (error) {
          console.log(error);
        }
      } catch (err) {
        console.log("Error trying to join the event ", err);
      } finally {
        setIsJoining(false);
      }
    } else {
      toaster();
    }
  };

  const changeEventStatus = async () => {
    // The problem
    const user = supabase.auth.user();
    const userId = user.id;
    const { data: event_participants, error } = await supabase
      .from("event_participants")
      .select("*")
      .eq("participant_id", userId);

    const { data: eventData, error: dataError } = await supabase
      .from("events")
      .select("*");

    let eventParticipantIds = event_participants.map((ep) => ep.event_id);
    let filteredEvents = eventData.filter((event) =>
      eventParticipantIds.includes(event.id)
    );
    console.log("filtered ", filteredEvents);

    eventData.map((evt) => {
      filteredEvents.map((filteredEvent) => {
        console.log("filt ", filteredEvent.id);
        console.log("event ", evt.id);
        console.log(filteredEvent.id === evt.id);
        if (filteredEvent.id === evt.id) {
          evt["isJoined"] = true;
        } else {
          evt["isJoined"] = false;
        }
      });
    });

    console.log("new event data to render", eventData);
  };

  return events.map((event, ix) => {
    return (
      <Box
        key={ix}
        p={4}
        rounded="sm"
        border="1px"
        borderColor="gray.100"
        boxShadow={"sm"}
      >
        <SimpleGrid
          display="flex"
          alignItems="center"
          justifyContent="space-between"
          columns={2}
        >
          <Box>
            <Stack>
              <Text fontSize={"2xl"} fontWeight="600">
                {event.title}
              </Text>
              <Text>
                {event ? event.description : "No description provided"}
              </Text>
              <Text>{`Organizer: ${event?.creator}`}</Text>
            </Stack>
            <Box pt={4}>
              <SimpleGrid columns={{ sm: 1, md: 2 }}>
                <Box>
                  <Text fontSize={"small"}>{`20 participants`}</Text>
                </Box>
                <Box>
                  <Text fontSize={"small"}>{`Date: ${event.start_date}`}</Text>
                </Box>
              </SimpleGrid>
            </Box>
          </Box>
          <Box>
            <Button bg="green.200" onClick={(e) => joinToEvent(event.id)}>
              {isJoining && eventId === event.id ? "Joining..." : "Join"}
            </Button>
          </Box>
          <Box>{isJoining && eventId === event.id && <Spinner />}</Box>
        </SimpleGrid>
      </Box>
    );
  });
};

export default EventCard;

Example:

const arr1 = [{
    "id": 82,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "Nuevo evento",
    "description": "en estos dias",
    "created_at": "2022-09-17T20:42:42.452948+00:00",
    "updated_at": "2022-09-17T20:42:42.452948+00:00",
    "start_date": "2022-09-23",
    "end_date": null,
    "longitude": -32.9296,
    "latitude": -71.2944,
    "creator": "rmi@mail.com",
    "place_name": null
  },
  {
    "id": 95,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "Virginia",
    "description": null,
    "created_at": "2022-09-17T21:13:40.728779+00:00",
    "updated_at": "2022-09-17T21:13:40.728779+00:00",
    "start_date": "2022-09-17",
    "end_date": null,
    "longitude": 35.4867,
    "latitude": 101.902,
    "creator": "rmi@mail.com",
    "place_name": null
  },
  {
    "id": 96,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "3",
    "description": null,
    "created_at": "2022-09-17T21:19:52.677742+00:00",
    "updated_at": "2022-09-17T21:19:52.677742+00:00",
    "start_date": "2022-09-17",
    "end_date": null,
    "longitude": -10.1511,
    "latitude": -75.3111,
    "creator": "rmi@mail.com",
    "place_name": null
  },
  {
    "id": 97,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "event",
    "description": "At indonesia beach",
    "created_at": "2022-09-17T21:34:53.360125+00:00",
    "updated_at": "2022-09-17T21:34:53.360125+00:00",
    "start_date": "2022-09-17",
    "end_date": null,
    "longitude": -6.17555,
    "latitude": 106.827,
    "creator": "rmi@mail.com",
    "place_name": "Indonesia"
  }
]

const arr2 = [{
    "id": 82,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "Nuevo evento",
    "description": "en estos dias",
    "created_at": "2022-09-17T20:42:42.452948+00:00",
    "updated_at": "2022-09-17T20:42:42.452948+00:00",
    "start_date": "2022-09-23",
    "end_date": null,
    "longitude": -32.9296,
    "latitude": -71.2944,
    "creator": "rmi@mail.com",
    "place_name": null
  },
  {
    "id": 95,
    "user_id": "e31cb09b-7a63-4581-9e3c-19f4730641bc",
    "title": "Virginia",
    "description": null,
    "created_at": "2022-09-17T21:13:40.728779+00:00",
    "updated_at": "2022-09-17T21:13:40.728779+00:00",
    "start_date": "2022-09-17",
    "end_date": null,
    "longitude": 35.4867,
    "latitude": 101.902,
    "creator": "rmi@mail.com",
    "place_name": null
  }
]

arr1.map((evt) => {
  arr2.map((filteredEvent) => {

    if (filteredEvent.id === evt.id) {
      evt['isJoined'] = true;
    } else {
      evt['isJoined'] = false;
    }
  })
});

console.log(arr1);

1 Answers

The problem is your nested loop. On each pass, it sets all but one element's isJoined to false.

You can simplify this greatly using the following

const eventParticipantIds = new Set(
  event_participants.map((ep) => ep.event_id)
);

const transformedEventData = eventData.map((evt) => ({
  ...evt,
  isJoined: eventParticipantIds.has(evt.id),
}));

A Set is optimised for value lookups so it performs better than an array.

Related