Search code examples
javascriptreactjsreduxredux-toolkit

my modal has a black background when i open it


I'm doing a table with delete and edit option and when I open a modal my modal has a black background. I found the problem and it is because when I click to open the modal it open multiple times. If I have 10 rows the modal open 10 times.

I'm using React-table-v7 and redux for my modal states.

black blackground

useTableHook.js

const resourcesColumns = useMemo(() => [
  {
    Header: 'delete',
    accessor: () => 'delete',
    disableSortBy: true,
    Cell: ({row}) => <div onClick={(event) => event.stopPropagation()}>
        <DeleteModal />
      </div>
  }
], [resourceData]);
    
useEffect(() => {
  hideColumns();
  setResourceData(data);
}, [data]);

My tableView.jsx

<tbody {...getTableBodyProps()} >
  {loading 
    ? <tr className="text-center">
        <td colSpan="5">
          <LoadingComponent />
        </td>
      </tr>
    : page.map((row) => {
      prepareRow(row);
    
      return (
        <tr {...row.getRowProps()} className="tb-row" onClick={() => showSelectedRow(row)} key={row}>
          {row.cells.map((cell, index) => <td
              {...cell.getCellProps()}
              key={index}
              className={`${index === 0 ? 'tb-body-txt-left py-2 px-2' : 'tb-body-txt'}`}
            >
              {cell.render('Cell')}
            </td>
          )}
        </tr>
      );
    })
  }
</tbody>

i'm using a hook for select the state

const modalState = () => {
  const ModalState = useSelector((state) => state.modal.isOpen);

  return ModalState;
};

my slice for modals

const modalSlice = createSlice({
  name: 'modal',
  initialState: {isOpen: false},
  reducers: {
    openModal: (state, action) => {
      state.isOpen = true;
    },
    closeModal: (state, action) => {
      state.isOpen = false;
    }
  }
});

export const {reducer} = modalSlice;
export default modalSlice.actions;

my modal view

 <>
      <i className="fa fa-trash-can text-primary ZoomIcon" onClick={handlers.opened} />
      <Modal show={show} onHide={handlers.closed} className="modalPosition">
        <Modal.Header closeButton>
          <Modal.Title>Atención !!</Modal.Title>
        </Modal.Header>
        <Modal.Body>Confirme que desea eliminar el recurso </Modal.Body>
        <Modal.Footer className="modalFooter">
          <Button variant="light" onClick={handlers.closed} autoFocus={true}>Close</Button>          
          <Button variant="primary" onClick={handlers.closed} autoFocus={true}>
            <i className="fa fa-check" aria-hidden="true"></i>Confirmar</Button>
        </Modal.Footer>
      </Modal>
    </>

here i pass my hook for the show property

  const modalState = useDeletehook();

 <DeleteModal show={modalState}/>

Do you know how can I fix this problem?


Solution

  • Issue

    The main issue is that you've only a single modal.isOpen state and multiple modals.

    const modalSlice = createSlice({
      name: 'modal',
      initialState: { isOpen: true },
      reducers: {
        openModal: (state, action) => {
          state.isOpen = true;
        },
        closeModal: (state, action) => {
          state.isOpen = false;
        }
      }
    });
    

    When state.modal.isOpen is true then all modals are opened.

    Solution

    You want to set some isOpen state to indicate that a specific modal should be shown. You can do this by using some id value that is related to the row data.

    const modalSlice = createSlice({
      name: 'modal',
      initialState: {
        isOpen: null
      },
      reducers: {
        openModal: (state, action) => {
          state.isOpen = action.payload;
        },
        closeModal: (state, action) => {
          state.isOpen = null;
        }
      }
    });
    

    To open a specific modal dispatch the openModal action and pass the id of a specific modal you want opened.

    dispatch(modalSlice.openModal(rowEl.id));
    
    dispatch(modalSlice.closeModal());
    
    <DeleteModal show={modalState.isOpen === rowEl.id}/>