reactjsmaterial-uireact-tsx

React Mui card refresh on react / Component refresh


import Typography from '@mui/material/Typography';
import { Grid, Card, CardContent, Box} from '@mui/material';
import MainCard from 'components/MainCard';
import UploadGP from './components/UploadGP';
import UploadExcel from './components/UploadExcel';
import UploadDataTable from './components/UploadDataTable';

export default function FCRUpload() {
  return (
    <MainCard title="Foreign Currency Risk">
      <Grid container spacing={2}>
        {/* Top: Long card spanning full width */}
        <Grid item xs={12}>
          <Box>
            <Card>
              <CardContent>
                <Typography variant="h6" gutterBottom>
                  Upload Excel File Here
                </Typography>
                <UploadExcel />
              </CardContent>
            </Card>
          </Box>
        </Grid>

        {/* Bottom: Two cards side by side */}
        <Grid item xs={12} md={6}>
          <Box mt={2}>
            <Card>
              <CardContent>
                <Typography variant="h6" gutterBottom>
                  Uploaded Foreign Currency Risk Details
                </Typography>
                <UploadDataTable />
              </CardContent>
            </Card>
          </Box>
        </Grid>

        <Grid item xs={12} md={6}>
          <Box mt={2}>
            <Card>
              <CardContent>
                <Typography variant="h6" gutterBottom>
                  Enter Gold Position
                </Typography>
                <UploadGP />
              </CardContent>
            </Card>
          </Box>
        </Grid>
      </Grid>
    </MainCard>
  );
}

this is my code which has 3 cards each carrying a method now I need to refresh other cards if one card gets changes

The first card has an Excel upload that sends data to the back end and inserts them into a table. The second card gets those data and shows them in a grid, but as the current code doesn't work, the grid shows old values.

I tried putting tab refresh, but it is not user-friendly. Is there a way I can refresh other cards if an action happens in one of them?


Solution

  • I found the answer for this

    Parent Component

    import MainCard from 'components/MainCard';
    import UploadGoldPosition from './components/UploadGP';
    import UploadExcel from './components/UploadExcel';
    import UploadDataTable from './components/UploadDataTable';
    
    export default function FCRUpload() {
    
      const [refresh, setRefresh] = useState(false);
      const [status, setStatus] = useState<number | null>(null);
    
      const handleFileUploadSuccess = () => {
        setRefresh(prev => !prev); // Toggle refresh state
      };
    
      const handleStatusChange = (childStatus: number | null) => {
        setStatus(childStatus); // Update the status based on what the child sends
      };  
    
      const getStatusLabel = (status: number | null): JSX.Element => {
        switch (status) {
          case 0:
            return <Chip color="warning" label="Pending" size="medium" variant="light" />;
          case 1:
            return <Chip color="success" label="Authorized" size="medium" variant="light" />;
          case 2:
            return <Chip color="error" label="Rejected" size="medium" variant="light" />;
          case 3:
            return <span>Submit First</span>;
          case 4:
            return <span>Upload First</span>
          default:
            return <span></span>;
        }
      };
    
    
      return (
        <MainCard>
          <Grid container spacing={2}>
            {/* Top: Long card spanning full width */}
            <Grid item xs={12}>
              <Box display="flex" justifyContent="space-between" sx={{ mt: 1, mr: 2 }}>
                <UploadExcel onUploadSuccess={handleFileUploadSuccess} status={status} />
                <Box>
                  Status : {getStatusLabel(status)}
                </Box>
              </Box>
            </Grid>
    
            {/* Bottom: Two cards side by side */}
            <Grid item xs={12} md={6}>
              <Box mt={2}>
                <Card>
                  <CardContent>
                    <Typography variant="h6" gutterBottom>
                      Uploaded Foreign Currency Risk Details
                    </Typography>
                    <UploadDataTable refresh={refresh} />
                  </CardContent>
                </Card>
              </Box>
            </Grid>
    
            <Grid item xs={12} md={6}>
              <Box mt={2}>
                <Card>
                  <CardContent>
                    <Typography variant="h6" gutterBottom>
                      Enter Gold Position
                    </Typography>
                    <UploadGoldPosition refresh={refresh} onStatusChange={handleStatusChange} />
                  </CardContent>
                </Card>
              </Box>
            </Grid>
          </Grid>
        </MainCard>
      );
    }
    

    First (Main) Child Component (only related code segment shown)

      const UploadExcel = ({ onUploadSuccess, status }: UploadExcelProps) => {
    
        const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
            try {
                const response = await FCRExcelUpload(file, userId);
            } catch (error : any) {
                errorNotification(error);
            } finally {
                onUploadSuccess();
            }
        };
    

    The Second child (only related code segment shown)

    const UploadDataTable = ({ refresh }: { refresh: boolean }) => {
    
      useEffect(() => {
        const fetchData = async () => {
          try {
            const response = await getFCRUploadData();
            setData(response.data);
    
          } catch (error) {
            errorNotification('Error occurred while populating the table:'+ error)
          }
        };
    
        fetchData();
    
      }, [refresh]); 
    

    Basically what this do is if the upload completes with or without success, there is a callback to the parent, which change a boolean value and pass it to other child or more refresh which triggers the useEffect in the child

    I create two methods to refresh and send a status, which is similar to the refresh but sends a value to Parent.