kgcusi
kgcusi

Reputation: 293

Double redux dispatch for some reason

Every time I delete my useEffect and delete an item the action listResidents() runs twice for some reason, this is just one example this mostly happens even in other components, I don't know why it does that. I tried to solve it myself but ends up not dispatching every time I delete or do something.


function Residents() {
  const RESIDENT_COLUMNS = useMemo(
    () => [
      {
        Header: 'First Name',
        accessor: 'fname',
        Filter: ColumnFilter,
      },
      {
        Header: 'Last Name',
        accessor: 'lname',
        Filter: ColumnFilter,
      },
      {
        Header: 'E-Mail',
        accessor: 'email',
        disableFilters: true,
        Filter: ColumnFilter,
      },
      {
        Header: 'Phone',
        accessor: 'phone',
        disableFilters: true,
      },
      {
        Header: 'Blk',
        accessor: 'blk',
        Filter: ColumnFilter,
      },
      {
        Header: 'Lot',
        accessor: 'lot',
        Filter: ColumnFilter,
      },
      {
        Header: 'Street',
        accessor: 'street',
        Filter: ColumnFilter,
      },
      {
        Header: 'Actions',
        accessor: 'actions',
        Cell: props => {
          return (
            <ButtonGroup spacing={2}>
              <IconButton
                colorScheme="blue"
                aria-label="Edit"
                icon={<EditIcon />}
                onClick={() => console.log(props.row.original._id)}
              />
              <IconButton
                colorScheme="red"
                aria-label="Edit"
                icon={<DeleteIcon />}
                onClick={() => deleteHandler(props.row.original._id)}
              />
            </ButtonGroup>
          );
        },
        disableFilters: true,
      },
    ],
    []
  );
  const dispatch = useDispatch();

  const residentList = useSelector(state => state.residentList);
  const { loading, error, residents } = residentList;

  const residentDelete = useSelector(state => state.residentDelete);
  const { success: successDelete } = residentDelete;

  useEffect(() => {
    dispatch(listResidents());
  }, [dispatch, successDelete]);

  const columns = RESIDENT_COLUMNS;
  const data = useMemo(() => residents, [residents]);

  const deleteHandler = id => {
    dispatch(deleteResident(id));
  };

  return (
    <Box p="2rem 8rem">
      <ModalResident />
      {loading ? (
        <Loader />
      ) : error ? (
        <Message status="error">{error}</Message>
      ) : (
        <BaseTable data={data} columns={columns} />
      )}
    </Box>
  );
}

export default Residents;

Upvotes: 0

Views: 68

Answers (1)

Adam Jenkins
Adam Jenkins

Reputation: 55613

If successDelete changes back to false - maybe that's what happens when you dispatch listResidents()? - then that's why.

This will fix it:

  useEffect(() => {
    if(!successDelete) return;
    dispatch(listResidents());
  }, [dispatch, successDelete]);

^ EDIT: This WON'T fix it, because now you won't dispatch the listResidents on mount.

So, the effect is of a gross way to do dispatch listResidents after delete (but it's fine on mount). It's best to do it in the delete handler. Depending on if you're using thunks or not, you might be able to do this:

  const deleteHandler = async id => {
    await dispatch(deleteResident(id));
    dispatch(listResidents())
  };

and get rid of the successDelete dependency from the effect altogether.

Or, maybe just dispatch a listResidents in the thunk (again, if you are using thunks) that does the delete and keep it out of the component code altogether.

Upvotes: 2

Related Questions