React-Redux最佳实践:从dispatch函数返回数据是否可行?
Hey there! No worries at all—we all start somewhere with React and Redux, so don't hesitate to ask questions. Let's break down your code, talk through what's working, and share some tips to make it even more robust.
First, let's clarify the flow:
- When your component mounts (
componentDidMount), it calls the Redux thunk actiongetUnitDatawith theunit_codefrom your route params. - The action presumably makes an API call (since you started writing
api.un...), returns a promise, and once resolved, you update your component's state with the fetchedunitdata, plus toggle loading/success states. - If the API call fails, you update the loading and success states to reflect the error.
Here are some common considerations for this pattern:
Should
unitlive in component state or Redux store?
If thisunitdata is only used in this single component, storing it in component state is totally fine. But if other components in your app need access to this data, it's better to save it to your Redux store instead. Here's how you'd adjust your action:export const getUnitData = unitCode => dispatch => { return api.getUnit(unitCode) // Assume your API method returns a promise .then(unit => { // Dispatch an action to save the unit to your Redux reducer dispatch({ type: 'SET_UNIT_DATA', payload: unit }); return unit; // Pass the unit through the promise chain for your component }) .catch(error => { // Optional: Dispatch an error action to track failures in the store dispatch({ type: 'UNIT_DATA_ERROR', payload: error }); throw error; // Re-throw to let the component catch the error }); };Then you'd map the store's unit data to your component props via
mapStateToProps, so you don't need to store it in component state anymore.Simplify async logic with
async/await
Yourthen/catchchain works, but usingasync/awaitcan make the code more readable, especially as your logic grows:async componentDidMount() { try { const unit = await this.props.getUnitData(this.props.match.params.unit_code); this.setState({ unit, loading: false, success: true }); } catch () { this.setState({ loading: false, success: false }); } }Ensure Redux Thunk is configured
Since your action is a thunk (a function that returns another function), double-check that you've added the thunk middleware to your Redux store. Without it, Redux won't know how to handle this action type:import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './your-reducer-file'; const store = createStore(rootReducer, applyMiddleware(thunk));Prevent state updates on unmounted components
If your component unloads before the API call finishes, callingsetStatewill trigger a React warning. Add a simple flag to avoid this:componentDidMount() { this._isMounted = true; this.props .getUnitData(this.props.match.params.unit_code) .then(unit => { if (this._isMounted) { this.setState({ unit, loading: false, success: true }); } }) .catch(() => { if (this._isMounted) { this.setState({ loading: false, success: false }); } }); } componentWillUnmount() { this._isMounted = false; }For a more elegant solution, you could use
AbortControllerto cancel the API request entirely when the component unmounts.
Make sure your API layer properly rejects the promise when a request fails (e.g., 404/500 status codes). If the API call doesn't throw an error on failure, your catch block won't run, and your loading state will get stuck as true.
内容的提问来源于stack exchange,提问作者MattyB

