0

我在同一页面中有 2 个表格组件:Resolved CasesAffected Cases. 每当我更新 Affectd Cases 表中的一行并对其进行验证时,它都会显示在Resolved Cases组件上。

AffectedCases.tsx:

import React, { useEffect } from 'react';
import { useDispatch, useSelector, shallowEqual } from "react-redux";
import MaterialTable, { Column } from 'material-table';
import TableIcons from "../../common/TableIcons";
import {
  fetchAffectedCasesRequest,
  updateAffectedCaseRequest
} from "./affectedCasesSlice";

import { AppState } from "../../app/rootReducer";

interface Row {
  caseId: number;
  name: string;
  email: string;
  bikeFrameNumber: number;
  caseResolved: number;
}

const AffectedCasesList = () => {
  const dispatch = useDispatch();
  const { officerId, cases } = useSelector((state: AppState) => ({
    officerId: state.affectedCases.officerId,
    cases: state.affectedCases.cases
  }), shallowEqual)

  const data = cases.map(c => ({ ...c }));
  const columns: Column<Row>[] = [
    { title: 'Case Id', field: 'caseId', type: 'numeric', editable: 'never' },
    { title: 'Name', field: 'name', editable: 'never' },
    { title: 'Email', field: 'email', editable: 'never' },
    { title: 'Bike Frame Number', field: 'bikeFrameNumber', type: 'numeric', editable: 'never' },
    { title: 'Case Resolved', field: 'caseResolved', lookup: { 1: 'true', 0: 'false' } }
  ];

  useEffect(() => {
    dispatch(fetchAffectedCasesRequest(officerId))
  }, [officerId, dispatch])

  return (
    <MaterialTable
      icons={TableIcons}
      columns={columns}
      data={data}
      editable={{
        onRowUpdate: (newData, oldData) => new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve();
            if (newData.caseResolved) {
              dispatch(updateAffectedCaseRequest({
                caseId: newData.caseId,
                officerId
              }))
            }
          }, 1000)
        }),
      }}
      options={{
        showTitle: false,
        rowStyle: {
          color: '#ffd600'
        }
      }}
      style={{
        width: '100%',
        backgroundColor: '#111010'
      }}
    />
  );
}

export default AffectedCasesList;

受影响的案例.ts:

import { AppThunk } from "../../app/store";
import {
  ReturnedCase,
  resolveCaseApi,
  AffectedCaseToUpdate,
  affectedCasesApi,
} from "../../api/reportedCasesApi";

interface AffectedCasesState {
  officerId: number;
  loading: boolean;
  cases: ReturnedCase[];
  error: string | null;
}
const initialState: AffectedCasesState = {
  officerId: 1,
  loading: false,
  cases: [],
  error: null
}


const affectedCase = createSlice({
  name: 'affectedCase',
  initialState,
  reducers: {
    officerCaseStart: (state) => {
      state.error = null;
    },
    startAffectedCasesFetch: (state) => {
      state.loading = true
    },
    fetchAffectedCasesSuccess: (state, action: PayloadAction<ReturnedCase[]>) => {
      state.cases = action.payload;
      state.loading = false;
    },
    updateAffectedCaseSuccess: (state, action: PayloadAction<number>) => {
      state.cases = state.cases.filter(c => c.caseId !== action.payload)
    },
    updateAffectedCaseError: (state, action: PayloadAction<string>) => {
      state.error = action.payload;
    },
    fetchAffectedCaseError: (state, action: PayloadAction<string>) => {
      state.error = action.payload;
      state.loading = false;
    },
  }
})

export const {
  officerCaseStart,
  startAffectedCasesFetch,
  fetchAffectedCasesSuccess,
  fetchAffectedCaseError,
  updateAffectedCaseError,
  updateAffectedCaseSuccess
} = affectedCase.actions


export default affectedCase.reducer;


export const updateAffectedCaseRequest = (caseToUpdate: AffectedCaseToUpdate): AppThunk => async dispatch => {
  try {
    dispatch(officerCaseStart());
    const updatedCaseId = await resolveCaseApi(caseToUpdate);
    dispatch(updateAffectedCaseSuccess(updatedCaseId))

  } catch (error) {
    let errorMessage = "Internal Server Error";
    if (error.response) {
      errorMessage = error.response.data.message;
    }
    dispatch(updateAffectedCaseError(errorMessage))
  }
}

export const fetchAffectedCasesRequest = (officerId: number): AppThunk => async dispatch => {
  try {
    dispatch(startAffectedCasesFetch())
    const affectedCasesList = await affectedCasesApi(officerId);
    dispatch(fetchAffectedCasesSuccess(affectedCasesList))
  } catch (error) {
    let errorMessage = "Internal Server Error";
    if (error.response) {
      errorMessage = error.response.data.message;
    }
    dispatch(fetchAffectedCaseError(errorMessage))
  }
}

已解决案例.tsx:

import React, { useEffect } from 'react';
import { useDispatch, useSelector, shallowEqual } from "react-redux";
import MaterialTable, { Column } from 'material-table';
import TableIcons from "../../common/TableIcons";

import {
  fetchResolvedCasesRequest
} from "./resolvedCasesSlice";

import { AppState } from "../../app/rootReducer";

interface Row {
  caseId: number;
  name: string;
  email: string;
  bikeFrameNumber: number;
}

const ResolvedCasesList = () => {
  const dispatch = useDispatch();
  const { officerId, cases } = useSelector((state: AppState) => ({
    officerId: state.resolvedCases.officerId,
    cases: state.resolvedCases.cases
  }), shallowEqual);

  const data = cases.map(c => ({ ...c }));
  const columns: Column<Row>[] = [
    { title: 'Case Id', field: 'caseId', type: 'numeric' },
    { title: 'Name', field: 'name' },
    { title: 'Email', field: 'email' },
    { title: 'Bike Frame Number', field: 'bikeFrameNumber', type: 'numeric' },
  ];

  useEffect(() => {
    dispatch(fetchResolvedCasesRequest(officerId))
  }, [officerId, dispatch])

  return (
    <MaterialTable
      icons={TableIcons}
      columns={columns}
      data={data}
      options={{
        showTitle: false,
        rowStyle: {
          color: '#ffd600'
        }
      }}
      style={{
        width: '100%',
        backgroundColor: '#111010'
      }}
    />
  );
}

export default ResolvedCasesList;

解决案例切片.ts:

import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { AppThunk } from "../../app/store";
import {
  BasicResult,
  resolvedCasesApi
} from "../../api/reportedCasesApi";

interface CasesState {
  officerId: number;
  loading: boolean;
  cases: BasicResult[];
  error: string | null;
}
const initialState: CasesState = {
  officerId: 1,
  loading: false,
  cases: [],
  error: null
}


const resolvedCases = createSlice({
  name: 'resolvedCases',
  initialState,
  reducers: {
    startResolvedCasesFetch: (state) => {
      state.loading = true
    },
    fetchResolvedCasesSuccess: (state, action: PayloadAction<BasicResult[]>) => {
      state.cases = action.payload;
      state.loading = false;
    },
    fetchResolvedCaseError: (state, action: PayloadAction<string>) => {
      state.error = action.payload;
      state.loading = false;
    }
  }
})

export const {
  startResolvedCasesFetch,
  fetchResolvedCasesSuccess,
  fetchResolvedCaseError,
} = resolvedCases.actions


export default resolvedCases.reducer;


export const fetchResolvedCasesRequest = (officerId: number): AppThunk => async dispatch => {
  try {
    dispatch(startResolvedCasesFetch())
    const resolvedCasesList = await resolvedCasesApi(officerId);
    dispatch(fetchResolvedCasesSuccess(resolvedCasesList));
  } catch (error) {
    let errorMessage = "Internal Server Error";
    if (error.response) {
      errorMessage = error.response.data.message;
    }
    dispatch(fetchResolvedCaseError(errorMessage))
  }
}

ResolvedCases组件仅在我刷新页面时更新,这是由于:

useEffect(() => {
    dispatch(fetchResolvedCasesRequest(officerId))
  }, [officerId, dispatch])

是否有任何解决方案可以在不刷新页面的情况下更新 ResolvedCases 表?

4

1 回答 1

0

每次更新 Affected Cases 中的一行时,应该触发带有 dispatch 的 useEffect。因此,例如,您可以在发生这种情况时发送带有某个 revisionId 的操作,并将您的 useEffect 重写为:

  const revisionIdPrev = useRef(props.revisionId)

  useEffect(() => {
    if (revisionId !== revisionIdPrev.current) {
      dispatch(fetchResolvedCasesRequest(officerId))
      revisionIdPrev.current = revisionId
    }
  }, [officerId, dispatch, revisionId])
于 2020-03-27T18:07:24.753 回答