React object not getting with updated redux store value

Viewed 68

I have a constant totalRowsSelected which I am trying to console in Processor function and inside processorColumnConfig Object in handleOnChange method. The issue is that it is printing the right value outside the processorColumnConfig Object but when used inside the processorColumnConfig Object, it is always printing the initial value which is a blank array. PLEASE ctrl + F totalRowsSelected and you'll understand what I am trying to say. Sorry for the long code.

Additional Info: I am using the react-table and passing the processorColumnConfig as a ColumnConfig prop.

Source code below:

import { useEffect, useState, Fragment } from 'react';
import { useSnackbar } from 'notistack';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'classnames';
import {
  getTempData,
  saveTempData,
  updateTableData,
  updateRowID,
  toggleData,
  toggleColumn,
  getCurrencyData,
  setSelectedRows,
  processCheckedData,
  setProcessedDataResponse,
  clearSelectedRows,
  setDeleteRows,
  deleteRows,
  setRowID,
  setSelectedView,
} from '../../actions/processor/processor.actions';
import { type, pathOr, clone, omit, lens, prop, set, assoc, pick, pluck, isEmpty } from 'ramda';
import ConfirmationModal from './ConfirmationModal';
import UpdateTempDB from './UpdateTempDB';
import ModifyCellData from './ModifyCellData';
import FundID from './FundID';
import { mockData } from '../../constants/FilesConstants';
import './Processor.scss';
import DatePickerComponent from './DatePickerComponent';

const tableColumnConfig = {
  key: 'dealsExposureTable',
  sortBy: 'dealDate',
  sortOrder: 'descending',
  pageSize: 10,
  total: 30,
  page: 1,
};
const Processor = () => {
  const selectedView = useSelector((state) => state.pcPerformance.processor.tempStorageData.selectedView);
  const processorColumnConfig = [
    {
      Header: 'id',
      id: 'id',
      accessor: 'Id',
      width: 10,
    },
    {
      Header: '',
      id: 'currentRowID',
      accessor: 'currentRowID',
      width: 0,
    },
    {
      Header: '',
      id: 'prevRowID',
      accessor: 'prevRowID',
      width: 0,
    },
    {
      Header: 'Fund Name',
      id: 'fundName',
      accessor: 'FundName',
      sticky: 'left',
      width: 160,
    },
    {
      Header: '',
      id: 'IsDuplicate',
      accessor: 'IsDuplicate',
      Cell: (row) => row.value && <External />,
      width: 20,
    },
    {
      Header: 'Fund ID',
      id: 'FundId',
      accessor: 'FundId',
      Cell: (row) => <FundID row={row} accessor={'FundId'} />,
      Filter: false,
      width: 96,
    },
    {
      Header: 'Currency',
      id: 'value_currency',
      accessor: (row) => {
        return (
          <Fragment key={row.Id}>
            <CurrencyDropdown rowId={row.Id} existingCurrency={row.CurrencyCode} />
          </Fragment>
        );
      },
      Filter: false,
      width: 160,
    },
    {
      Header: 'Total LP Commitment',
      id: 'lpCommitment',
      accessor: 'LPCommitment',
      Cell: (row) => {
        return (
          <div className="input_wraper">
            <Input
              type="text"
              value={type(row.value) === 'Object' ? row.value.value : row.value}
              onChange={(e) => handleOnChange(e.target.value, 'LPCommitment', row.value, row.row.original.Id)}
              style={{ 'text-align': 'right' }}
            />
            {hasValidationError(row.value) && (
              <span id={`LPCommitment-${row.row.original.Id}`}>
                {row.value.SoftValidation && <Away />}
                {row.value.HardValidation && <Idle />}
                <Tooltip
                  title={row.value.ErrorMessage}
                  target={`LPCommitment-${row.row.original.Id}`}
                  position="bottom"
                />
              </span>
            )}
          </div>
        );
      },
      Filter: false,
      width: 160,
    },
    // <ModifyCellData row={row} accessor={'LPCommitment'}
    //                                  onCellChange = {handleOnChange} />
    {
      Header: 'Total Capital Called ',
      id: 'lpContribution',
      accessor: 'LPContribution',
      Cell: (row) => {
        return (
          <div className="input_wraper">
            <Input
              type="text"
              value={precise(type(row.value) === 'Object' ? row.value.value : row.value)}
              onChange={(e) => handleOnChange(e.target.value, 'LPContribution', row.value, row.row.original.Id)}
              style={{ 'text-align': 'right' }}
            />
            {hasValidationError(row.value) && (
              <span id={`LPContribution-${row.row.original.Id}`}>
                {row.value.SoftValidation && <Away />}
                {row.value.HardValidation && <Idle />}
                <Tooltip
                  title={row.value.ErrorMessage}
                  target={`LPContribution-${row.row.original.Id}`}
                  position="bottom"
                />
              </span>
            )}
          </div>
        );
      },
      Filter: false,
      width: 160,
    },
    {
      Header: 'Total Distributions',
      id: 'lpDistribution',
      accessor: 'LPDistribution',
      Cell: (row) => {
        return (
          <div className="input_wraper">
            <Input
              type="text"
              value={precise(type(row.value) === 'Object' ? row.value.value : row.value)}
              onChange={(e) => handleOnChange(e.target.value, 'LPDistribution', row.value, row.row.original.Id)}
              style={{ 'text-align': 'right' }}
            />
            {hasValidationError(row.value) && (
              <span id={`LPDistribution-${row.row.original.Id}`}>
                {row.value.SoftValidation && <Away />}
                {row.value.HardValidation && <Idle />}
                <Tooltip
                  title={row.value.ErrorMessage}
                  target={`LPDistribution-${row.row.original.Id}`}
                  position="bottom"
                />
              </span>
            )}
          </div>
        );
      },
      Filter: false,
      width: 160,
    },
    {
      Header: 'Unrealized Value',
      id: 'fundMarketValue',
      accessor: 'FundMarketValue',
      Cell: (row) => {
        return (
          <div className="input_wraper">
            <Input
              type="text"
              value={precise(type(row.value) === 'Object' ? row.value.value : row.value)}
              onChange={(e) => handleOnChange(e.target.value, 'FundMarketValue', row.value, row.row.original.Id)}
              style={{ 'text-align': 'right' }}
            />
            {hasValidationError(row.value) && (
              <span id={`FundMarketValue-${row.row.original.Id}`}>
                {row.value.SoftValidation && <Away />}
                {row.value.HardValidation && <Idle />}
                <Tooltip
                  title={row.value.ErrorMessage}
                  target={`FundMarketValue-${row.row.original.Id}`}
                  position="bottom"
                />
              </span>
            )}
          </div>
        );
      },
      Filter: false,
      width: 160,
    },
    {
      Header: 'Net IRR',
      id: 'reportedIRR',
      accessor: 'ReportedIRR',
      Cell: (row) => {
        return (
          <div className="input_wraper">
            <Input
              type="text"
              value={type(row.value) === 'Object' ? precise(row.value.value) : precise(row.value)}
              onChange={(e) => handleOnChange(e.target.value, 'ReportedIRR', row.value, row.row.original.Id)}
              style={{ 'text-align': 'right' }}
            />
            {hasValidationError(row.value) && (
              <span id={`ReportedIRR-${row.row.original.Id}`}>
                {row.value.SoftValidation && <Away />}
                {row.value.HardValidation && <Idle />}
                <Tooltip
                  title={row.value.ErrorMessage}
                  target={`ReportedIRR-${row.row.original.Id}`}
                  position="bottom"
                />
              </span>
            )}
          </div>
        );
      },
      Filter: false,
      width: 96,
    },
    {
      Header: 'Source ID',
      id: 'sourceId',
      accessor: 'SourceId',
      Cell: (row) => <FundID row={row} accessor={'SourceId'} />,
      Filter: false,
      width: 96,
    },
    {
      Header: 'Date Reported',
      id: 'dateReported',
      accessor: 'DateReported',
      Cell: (row) => {
        return (
          <Fragment key={pathOr(null, ['row', 'original', 'Id'], row)}>
            <DatePickerComponent row={row} rowValue={row.value} />
          </Fragment>
        );
      },
      Filter: false,
      width: 250,
    },
  ];

  const { enqueueSnackbar } = useSnackbar();
  const dispatch = useDispatch();

  const [hiddenColumns, setHiddenColumns] = useState(['id', 'prevRowID', 'currentRowID']);
  const [buttonText, setButtonText] = useState('Absolute');
  const [selectedRow, setSelectedRow] = useState([]);
  const [rowID, setPrevRow] = useState('');
  const [numOfRows, setNumOfRow] = useState(0);
  let tableData = useSelector((state) => state.pcPerformance.processor.tempStorageData.tempDataAbsolute || []);
  const isDeleteClicked = useSelector((state) => state.pcPerformance.processor.setDeleteRows);
  const isLatestEditedRowSaved = useSelector(
    (state) => state.pcPerformance.processor.latestEditedRows.isLatestEditedRowSaved,
  );
  const selectedRowIdWithoutError = useSelector(
    (state) => state.pcPerformance.processor.checkedRows.rowsIdWithoutError,
  );
  const totalRowsSelected = useSelector((state) => state.pcPerformance.processor.checkedRows.selectedRows);
  const isProcessDataSuccess = useSelector((state) => state.pcPerformance.processor.processedData.isSuccess);
  const isClearSelectedRows = useSelector((state) => state.pcPerformance.processor.clearSelectedRows);
  const tablePercentData = useSelector(
    (state) => state.pcPerformance.processor.tempStorageData.tempDataPercentage || [],
  );
  const onChangeParent = () => {
    console.log('called from child component');
  };
  console.log('Helloworld outside', totalRowsSelected);
  useEffect(() => {
    dispatch(getTempData());
    dispatch(getCurrencyData());
  }, []);

  const rowData = (row) => {
    // Dispatching set and clear rows actions
    if (numOfRows < row.length) {
      const data = row[row.length - 1];
      saveToMongo(data);
    }
    setNumOfRow(row.length);
    console.log('row length ', numOfRows, row.length);
    dispatch(setSelectedRows(row));
    dispatch(clearSelectedRows(false));
    console.log('row id ', row, row.id);
    const ids = row.map((data) => {
      if (data) {
        return data.id;
      }
    });
    setSelectedRow(ids);
    console.log('ids ', ids);
  };

  const updateRowData = (row) => {
    if (rowID !== '' && row.id !== rowID) {
      const data = tableData.filter((data) => data.id === rowID);
      saveToMongo(data[0]);
    }
    setPrevRow(row.id);
    console.log(rowID);
  };

  const isNumber = (n) => {
    return !isNaN(parseFloat(n)) && !isNaN(n - 0);
  };

  const handleOnChange = (val, accessor, origVal, rowID) => {
    var regex = /^\d*\.?\d*$/;
    console.log('Helloworld inside', totalRowsSelected);
    if (selectedView === 'Percentage' && !val.match(regex) && isNaN(val)) {
      if ('error'.indexOf(val) > -1) {
        enqueueSnackbar('Please resolve validation errors', { variant: 'error', preventDuplicate: true });
      } else {
        enqueueSnackbar('Please enter numbers only', { variant: 'error', preventDuplicate: true });
      }
    } else {
      dispatch(updateTableData(val, accessor, origVal, rowID));
    }
  };

  useEffect(() => {
    if (isProcessDataSuccess != null) {
      if (isProcessDataSuccess) {
        if (selectedRowIdWithoutError.length !== totalRowsSelected.length) {
          enqueueSnackbar(
            ` Only ${selectedRowIdWithoutError.length}/${totalRowsSelected.length} rows were processed due to hard validation failures`,
            { variant: 'warning' },
          );
        } else {
          enqueueSnackbar('All rows processed', { variant: 'success' });
        }

        setSelectedRows([]);
      } else {
        enqueueSnackbar('No rows processed', { variant: 'error' });
      }
      dispatch(setProcessedDataResponse({}));
    }
  }, [isProcessDataSuccess]);

  const precise = (num) => {
    // Added regex because toFixed doesn't let user enter a decimal, hence excluded number followed by decimal
    const decimalRegex = /^\d*\.$/;
    if (!num || !isNumber(num) || String(num).match(decimalRegex)) {
      return num;
    }
    return Number(Number.parseFloat(num).toFixed(2));
  };

  console.log('table data ', tableData, isDeleteClicked);
  return (
    <Fragment>
      <div>
        <div>
          {/*<Button text={buttonText} type="primary" size="xSmall" handleOnClick={onToggle} />*/}
          <ToggleSwitch
            size={'xSmall'}
            optionOneText="Absolute"
            optionOneValue="Absolute"
            optionTwoText="Percentage"
            optionTwoValue="Percentage"
            selectedValue={selectedView}
            onChange={(value) => dispatch(setSelectedView(value))}
          />
        </div>
          <Table
            key={tableColumnConfig.key}
            title="Processor"
            columnConfig={processorColumnConfig}
            hiddenColumns={hiddenColumns}
            tableData={tableData}
            total={tableColumnConfig.total}
            viewSettingsEnabled={false}
            virtualisedEnabled={false}
            checkboxesEnabled
            initialSortBy={[{ id: tableColumnConfig.sortBy, desc: tableColumnConfig.sortOrder === 'descending' }]}
            onRowSelect={(row) => rowData(row)}
            rowClickEnabled={true}
            onRowClick={(row) => updateRowData(row)}
            actionBarEnabled={true}
            topPaginationEnabled={false}
            stickyColumnsEnabled
            clearAllSelectedRows={isClearSelectedRows}
            dataRequestFunction={() => null}
            actionBarActions={[
              {
                label: 'Match Fund',
                action: () => alert('Action Function Called - remember to set the action function'),
              },
              {
                label: 'Add as New ',
                action: () => alert('Action Function Called - remember to set the action function'),
              },
              {
                label: 'Delete ',
                action: () => {
                  dispatch(setDeleteRows(true));
                },
              },
              {
                label: 'Process ',
                action: () => {
                  dispatch(processCheckedData(selectedRowIdWithoutError));
                  enqueueSnackbar('Processing your data');
                },
              },
            ]}
          />
        {isDeleteClicked && <ConfirmationModal row={selectedRow} val={isDeleteClicked} />}
      </div>
    </Fragment>
  );
};

export default Processor;
0 Answers
Related