如何编写更新Redux Store的Action?React-Redux数据填充咨询
Hey there! Let's walk through how to get your WebApi data into React Table using React-Redux, plus how to write the actions that update your Redux store. I'll tie this all together with the code snippets you shared.
1. Fetching Data & Populating React Table
First, your Dictionary component (linked via the route <Route path="/Dictionary/:dictionaryName" component={Dictionary} />) will need to:
- Grab the
dictionaryNameparameter from the URL - Fetch the corresponding data from your WebApi (using the TypeWriter-generated client)
- Pass the fetched data from Redux to React Table
Here's how that might look in your component:
import { useParams } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import { useEffect } from 'react'; // Adjust the import path for React Table based on your version import { useTable } from '@tanstack/react-table'; const Dictionary = () => { // Get the dictionary name from the route params const { dictionaryName } = useParams<{ dictionaryName: string }>(); const dispatch = useDispatch(); // Pull the dictionary data from Redux store const dictionaryData = useSelector((state: RootState) => state.singleDictionary.singleDictionary); // Fetch data when the component mounts or dictionaryName changes useEffect(() => { if (dictionaryName) { dispatch(fetchSingleDictionary(dictionaryName)); } }, [dictionaryName, dispatch]); // Define your React Table columns (match your SingleDictionary structure) const columns = [ { header: 'ID', accessorKey: 'id' }, // For @tanstack/react-table v8+ { header: 'Label', accessorKey: 'label' }, // Add other columns as needed ]; // Set up React Table hooks const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({ columns, data: dictionaryData, }); return ( <table {...getTableProps()}> <thead> {headerGroups.map(headerGroup => ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map(column => ( <th {...column.getHeaderProps()}>{column.render('Header')}</th> ))} </tr> ))} </thead> <tbody {...getTableBodyProps()}> {rows.map(row => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.getVisibleCells().map(cell => ( <td {...cell.getCellProps()}>{cell.render('Cell')}</td> ))} </tr> ); })} </tbody> </table> ); }; export default Dictionary;
2. Writing Redux Actions to Update the Store
To update your Redux store with the fetched data, you'll need action types, action creators (including async ones for API calls), and a reducer. Let's build this step by step.
Step 1: Define Action Types
First, create constants for your action types to avoid typos:
// src/features/singleDictionary/actionTypes.ts export const FETCH_DICTIONARY_REQUEST = 'FETCH_DICTIONARY_REQUEST'; export const FETCH_DICTIONARY_SUCCESS = 'FETCH_DICTIONARY_SUCCESS'; export const FETCH_DICTIONARY_FAILURE = 'FETCH_DICTIONARY_FAILURE';
Step 2: Create Action Creators
Since you're making an async API call, we'll use Redux Thunk to handle the async logic. Here's how to write the action creators:
// src/features/singleDictionary/actions.ts import { Dispatch } from 'redux'; import { WebApi } from '../path-to-your-typewriter-generated-api'; // Adjust path import { FETCH_DICTIONARY_REQUEST, FETCH_DICTIONARY_SUCCESS, FETCH_DICTIONARY_FAILURE, } from './actionTypes'; // Define action interfaces for type safety interface FetchDictionaryRequestAction { type: typeof FETCH_DICTIONARY_REQUEST; } interface FetchDictionarySuccessAction { type: typeof FETCH_DICTIONARY_SUCCESS; payload: WebApi.SingleDictionary[]; } interface FetchDictionaryFailureAction { type: typeof FETCH_DICTIONARY_FAILURE; payload: string; } export type SingleDictionaryAction = | FetchDictionaryRequestAction | FetchDictionarySuccessAction | FetchDictionaryFailureAction; // Async action creator to fetch data export const fetchSingleDictionary = (dictionaryName: string) => async (dispatch: Dispatch<SingleDictionaryAction>) => { // Dispatch a "request" action to track loading state (optional but useful) dispatch({ type: FETCH_DICTIONARY_REQUEST }); try { // Call your TypeWriter-generated WebApi client const apiResponse = await WebApi.SingleDictionary.getByDictionaryName(dictionaryName); // Dispatch success action with the fetched data dispatch({ type: FETCH_DICTIONARY_SUCCESS, payload: apiResponse.data, }); } catch (error) { // Dispatch failure action with error message dispatch({ type: FETCH_DICTIONARY_FAILURE, payload: error instanceof Error ? error.message : 'Failed to load dictionary data', }); } };
Step 3: Update the Reducer
Now, update your reducer to handle these actions and modify the state:
// src/features/singleDictionary/reducer.ts import { SingleDictionaryState, initialState } from './state'; import { SingleDictionaryAction, FETCH_DICTIONARY_SUCCESS } from './actions'; export const singleDictionaryReducer = ( state: SingleDictionaryState = initialState, action: SingleDictionaryAction ): SingleDictionaryState => { switch (action.type) { case FETCH_DICTIONARY_SUCCESS: return { ...state, singleDictionary: action.payload, }; // Add cases for request/failure if you want to track loading/error states // case FETCH_DICTIONARY_REQUEST: // return { ...state, isLoading: true }; // case FETCH_DICTIONARY_FAILURE: // return { ...state, error: action.payload, isLoading: false }; default: return state; } };
Step 4: Wire Up the Store
Make sure your reducer is added to your root Redux store (with Thunk middleware enabled for async actions):
// src/store.ts import { combineReducers, createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import { singleDictionaryReducer } from './features/singleDictionary/reducer'; const rootReducer = combineReducers({ singleDictionary: singleDictionaryReducer, }); export type RootState = ReturnType<typeof rootReducer>; export const store = createStore(rootReducer, applyMiddleware(thunk));
Quick Notes
- Double-check your TypeWriter-generated WebApi methods to ensure they match your server-side WebApi routes (e.g., HTTP method, parameter names).
- Consider adding
isLoadinganderrorfields to yourSingleDictionaryStateto show loading spinners or error messages to users. - If you're using a newer version of Redux (like Redux Toolkit), you can simplify this code with
createSliceandcreateAsyncThunk—it reduces boilerplate significantly!
内容的提问来源于stack exchange,提问作者tesicg

