在不同页面为React组件绑定不同action creator的问题求助
Hey, this is such a common and valid use case when building reusable React components with Redux! Let’s break down a couple of clean, maintainable ways to solve this:
1. Pass Action Creators as Props (Recommended)
Since your Foo component is already designed to accept an onClick prop, the simplest and most idiomatic approach is to keep Foo as a pure presentational component (no Redux connect inside it) and let the parent page components handle connecting to Redux and passing the right action creator.
First, update Foo.jsx to remove the Redux connect logic entirely:
// Foo.jsx const Foo = ({ onClick, label = "Click Me", ...rest }) => { return ( <button onClick={onClick} {...rest}> {label} </button> ); }; export default Foo;
Then, in each page where you use Foo, connect the page to Redux and pass the bound action creator as the onClick prop:
Page A (uses actionCreatorA)
// PageA.jsx import Foo from "./Foo"; import { actionCreatorA } from "../actions"; import { connect } from "react-redux"; const PageA = ({ handleClick }) => { return <Foo onClick={handleClick} label="Do Action A" />; }; // Map the action creator directly (Redux automatically binds it to dispatch) const mapDispatchToProps = { handleClick: actionCreatorA, }; export default connect(null, mapDispatchToProps)(PageA);
Page B (uses actionCreatorB)
// PageB.jsx import Foo from "./Foo"; import { actionCreatorB } from "../actions"; import { connect } from "react-redux"; const PageB = ({ handleClick }) => { return <Foo onClick={handleClick} label="Do Action B" />; }; const mapDispatchToProps = { handleClick: actionCreatorB, }; export default connect(null, mapDispatchToProps)(PageB);
This keeps Foo completely decoupled from Redux, making it way more reusable across your app (you could even use it in non-Redux parts if needed!).
2. Allow Custom Actions in the Connected Foo Component
If you prefer to keep Foo connected to Redux but still want flexibility, you can modify mapDispatchToProps to accept a custom action creator via props. This lets you override the default action when needed.
// Foo.jsx import { connect } from "react-redux"; import { defaultActionCreator } from "../actions"; const Foo = ({ onClick }) => { return <button onClick={onClick}>Click Me</button>; }; // Use the action creator from props if provided, fall back to the default const mapDispatchToProps = (dispatch, ownProps) => { return { onClick: () => { const action = ownProps.customAction ? ownProps.customAction() : defaultActionCreator(); dispatch(action); }, }; }; export default connect(null, mapDispatchToProps)(Foo);
Then use it in your pages like this:
// PageA.jsx import Foo from "./Foo"; import { actionCreatorA } from "../actions"; const PageA = () => { return <Foo customAction={actionCreatorA} />; };
3. Modern Approach: Use Redux Hooks
If you're using functional components and Redux Toolkit (which you should be for modern Redux!), you can skip connect entirely and use the useDispatch hook in your parent pages to bind the action creator directly:
// PageA.jsx import Foo from "./Foo"; import { useDispatch } from "react-redux"; import { actionCreatorA } from "../actions"; const PageA = () => { const dispatch = useDispatch(); const handleClick = () => dispatch(actionCreatorA()); return <Foo onClick={handleClick} />; }; export default PageA;
This is even cleaner and avoids the boilerplate of connect.
Final Recommendation
Stick with approach 1 or 3—they keep your presentational components focused on UI and your container/pages handling Redux logic, which follows the single-responsibility principle and makes your code easier to maintain.
内容的提问来源于stack exchange,提问作者Kirill

