如何在不接收Redux Store数据到React组件的情况下分发异步请求?
嘿,这两个问题都是Redux开发里很典型的场景,我来给你一步步拆解清楚~
问题1:如何在无需将Redux Store数据接收至React组件的情况下进行分发?
其实核心很简单:只要能拿到Redux的dispatch方法,就能分发Action,完全不需要让组件订阅或接收Store里的任何状态。这里有两种常用的实现方式:
方式1:使用Redux Hooks(现代推荐写法)
通过useDispatch钩子直接获取dispatch方法,组件不需要和Store状态做任何绑定:
import { useDispatch } from 'react-redux'; import { yourActionCreator } from './actions'; const MyComponent = () => { const dispatch = useDispatch(); const handleTrigger = () => { // 直接分发Action,组件完全不依赖Store数据 dispatch(yourActionCreator()); }; return <button onClick={handleTrigger}>触发Action</button>; }; export default MyComponent;
方式2:使用connect高阶组件
如果是类组件或者习惯用旧写法,只需要给connect的第一个参数传null(表示不订阅Store状态),只定义mapDispatchToProps即可:
import { connect } from 'react-redux'; import { yourActionCreator } from './actions'; const MyComponent = ({ dispatchYourAction }) => { return <button onClick={dispatchYourAction}>触发Action</button>; }; // 第一个参数传null,跳过状态订阅 export default connect(null, { dispatchYourAction: yourActionCreator })(MyComponent);
问题2:异步Action需要用到Store中不用于渲染的数据,如何在不传给组件的情况下完成分发?
你提到的场景里,dataNotUsedForRendering只需要发给服务器,不需要在组件里渲染,那完全没必要把它传到组件里。我们可以用Redux Thunk中间件(处理异步Action的标准方案),在Action创建函数里直接获取Store状态,组件只负责触发这个Action就行。
步骤1:确保配置了Redux Thunk中间件
首先要在Store初始化时加入Thunk,这样才能支持返回函数的Action:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers'; // 把thunk加入中间件链 const store = createStore(rootReducer, applyMiddleware(thunk)); export default store;
步骤2:编写带getState的Thunk Action
Thunk Action允许我们返回一个函数,这个函数能拿到dispatch和getState方法——后者可以直接获取Store里的所有状态,包括你需要的dataNotUsedForRendering:
// actions.js export const sendDataToServer = () => { return async (dispatch, getState) => { // 直接从Store里取需要发送的数据,完全不用传到组件 const { dataNotUsedForRendering } = getState().yourReducerName; try { // 发起异步请求 const response = await fetch('/api/your-endpoint', { method: 'POST', body: JSON.stringify(dataNotUsedForRendering), headers: { 'Content-Type': 'application/json' } }); const result = await response.json(); // 可选:分发成功Action更新Store(如果需要的话) dispatch({ type: 'SEND_DATA_SUCCESS', payload: result }); } catch (error) { dispatch({ type: 'SEND_DATA_FAILURE', payload: error.message }); } }; };
步骤3:组件中直接分发这个Thunk Action
组件不需要接收任何Store数据,只需要触发这个Action就行:
// Hooks写法 import { useDispatch } from 'react-redux'; import { sendDataToServer } from './actions'; const MyComponent = () => { const dispatch = useDispatch(); const handleSend = () => { // 直接分发Thunk Action,组件完全不知道dataNotUsedForRendering的存在 dispatch(sendDataToServer()); }; return <button onClick={handleSend}>发送数据到服务器</button>; }; export default MyComponent;
如果用connect写法,同样不需要订阅状态:
import { connect } from 'react-redux'; import { sendDataToServer } from './actions'; const MyComponent = ({ sendData }) => { return <button onClick={sendData}>发送数据到服务器</button>; }; // 只传mapDispatchToProps,跳过状态订阅 export default connect(null, { sendData: sendDataToServer })(MyComponent);
这里要解释下你提到的“获取到的是Connect(MyComponent)的props而非MyComponent的props”——其实是因为如果在mapDispatchToProps里想访问组件的props是可以的,但在这个场景里我们根本不需要组件的props,直接通过getState从Store拿数据就好,完全和组件解耦,也避免了不必要的props传递。
内容的提问来源于stack exchange,提问作者Frozen Crayon

