Vanessa Ventura
Vanessa Ventura

Reputation: 99

How to have button's onClick override as={Link} to={} (anchor tag)?

enter image description here

I have a button inside my <List.Item as={Link} to={/lists/${list.id}}> which I want to activate but the as={Link} has converted the entire greyed selection an anchor tag; this makes it so, when I click the button, it just links me to the route rather than executing onClick delete functionality. How can I maintain the onClick delete functionality of the <DeleteButton> but still allow for the rest of the List.item (greyed section) to keep link functionality ?

Profile.js (List component in photo above)

import React, { useContext } from "react";
import { useQuery } from "@apollo/react-hooks";
import { List, Image } from "semantic-ui-react";
import { Link } from "react-router-dom";

import ListForm from "../components/ListForm";
import DeleteButton from "../components/DeleteButton";
import { AuthContext } from "../context/auth";
// import ListForm from "../components/ListForm";
import { FETCH_LISTS_QUERY } from "../util/graphql";
import "../RankList.css";

function Profile(props) {
  const { user } = useContext(AuthContext);

  let lists = "";
  const { loading, data, error } = useQuery(FETCH_LISTS_QUERY);

  console.log(error);
  console.log(`Loading: ${loading}`);
  console.log(data);

  if (data) {
    lists = { data: data.getLists.filter((l) => l.username === user.username) };
    console.log(lists);
  }

  // function deleteListCallback() {
  //   props.history.push("/");
  // }

  return (
    <List selection verticalAlign="middle">
      {user && <ListForm />}
      {lists.data &&
        lists.data.map((list) => (
          <List.Item as={Link} to={`/lists/${list.id}`}>
            <Image avatar src="/images/avatar/small/helen.jpg" />
            <List.Content>
              <List.Header>{list.title}</List.Header>
            </List.Content>
            <DeleteButton listId={list.id} />
          </List.Item>
        ))}
    </List>
  );
}

export default Profile;

DeleteButton.js (Delete button component in photo above)

import React, { useState } from "react";
import gql from "graphql-tag";
import { useMutation } from "@apollo/react-hooks";

import { Button, Confirm, Icon } from "semantic-ui-react";

import { FETCH_LISTS_QUERY } from "../util/graphql";
import MyPopup from "../util/MyPopup";

function DeleteButton({ listId, listItemId, commentId, callback }) {
  const [confirmOpen, setConfirmOpen] = useState(false);

  let mutation;

  if (listItemId) {
    mutation = DELETE_LIST_ITEM_MUTATION
  } else if (commentId) {
    mutation = DELETE_COMMENT_MUTATION
  } else {
    mutation = DELETE_LIST_MUTATION
  }

  // const mutation = commentId ? DELETE_COMMENT_MUTATION : DELETE_LIST_MUTATION;

  const [deleteListOrComment] = useMutation(mutation, {
    update(proxy) {
      setConfirmOpen(false);
      // remove list from cache
      if (!commentId && !listItemId) {
        const data = proxy.readQuery({
          query: FETCH_LISTS_QUERY,
        });
        const resLists = data.getLists.filter((p) => p.id !== listId);
        proxy.writeQuery({
          query: FETCH_LISTS_QUERY,
          data: { getLists: [...resLists] },
        });
      }

      if (callback) callback();
    },
    variables: {
      listId,
      commentId,
    },
    onError(err) {
      console.log(err.graphQLErrors[0].extensions.exception.errors);
    },
  });

  return (
    <>
      <MyPopup content={commentId ? "Delete comment" : "Delete list"}>
        <Button
          as="div"
          color="red"
          floated="right"
          onClick={() => setConfirmOpen(true)}
        >
          <Icon name="trash" style={{ margin: 0 }} />
        </Button>
      </MyPopup>
      <Confirm
        open={confirmOpen}
        onCancel={() => setConfirmOpen(false)}
        onConfirm={deleteListOrComment}
      />
    </>
  );
}

const DELETE_LIST_MUTATION = gql`
  mutation deleteList($listId: ID!) {
    deleteList(listId: $listId)
  }
`;

const DELETE_LIST_ITEM_MUTATION = gql`
  mutation deleteListItem($listId: ID!, $listItemId: ID!) {
    deleteListItem(listId: $listId, listItemId: $listItemId) {
      id
      comments {
        id
        username
        createdAt
        body
      }
      commentCount
    }
  }
`;

const DELETE_COMMENT_MUTATION = gql`
  mutation deleteComment($listId: ID!, $commentId: ID!) {
    deleteComment(listId: $listId, commentId: $commentId) {
      id
      comments {
        id
        username
        createdAt
        body
      }
      commentCount
    }
  }
`;
export default DeleteButton;

Upvotes: 1

Views: 1203

Answers (2)

Drew Reese
Drew Reese

Reputation: 203292

You can add preventDefualt (and possibly stopPropagation if necessary) to the event passed to the button's onClick handler.

<Button
  as="div"
  color="red"
  floated="right"
  onClick={e => {
    e.preventDefualt();
    setConfirmOpen(true);
  }}
>

Edit runtime-dream-ceoef

Upvotes: 1

user12807268
user12807268

Reputation:

One solution could be to create a custom link component and redirect with the push method of the history object. With this method you can add a ref to your DeleteButton and check if the event target isn't the DeleteButton component, then redirect. I don't think it's the cleanest solution, I made a little sandbox

Upvotes: 0

Related Questions