React Redux中容器组件的Hooks替代方案及项目结构疑问
Hey there! Let's break down your questions step by step—this is a super common shift when moving from class-based Redux to Hooks, so you're definitely not alone here.
1. Do we still need to separate container and presentational components?
Short answer: The core idea still matters, but the implementation changes drastically.
Before Hooks, container components were the "middlemen" connecting Redux to presentational components via props. With Hooks like useSelector and useDispatch, you can directly access Redux state and actions inside any component—so you don't need dedicated container components anymore.
Instead of splitting components into "container" vs "presentational", think in terms of logic encapsulation with custom Hooks:
- Keep your UI-focused components clean (they handle rendering, user interactions, and styling)
- Extract Redux-related logic (data fetching, state selection, action dispatching) into reusable custom Hooks. These Hooks act like the modern replacement for container components, but they're more flexible and reusable across multiple UI components.
2. Should we inject state/actions via props or import them directly in components?
With Hooks, you almost never need to inject Redux state or actions via props anymore.
Instead:
- Use
useSelectordirectly in your component (or custom Hook) to grab the state you need:const user = useSelector(state => state.user.profile); const isLoading = useSelector(state => state.user.loading); - Use
useDispatchto get a dispatch function, then call your action creators directly:const dispatch = useDispatch(); const handleUpdateUser = (data) => dispatch(updateUser(data));
For reusable logic, wrap these calls into a custom Hook to keep your UI components lean:
// hooks/useUser.js import { useSelector, useDispatch } from 'react-redux'; import { fetchUser, updateUser } from '../slices/userSlice'; export const useUser = () => { const user = useSelector(state => state.user.profile); const isLoading = useSelector(state => state.user.loading); const dispatch = useDispatch(); const loadUser = (userId) => dispatch(fetchUser(userId)); const saveUserChanges = (data) => dispatch(updateUser(data)); return { user, isLoading, loadUser, saveUserChanges }; }; // components/UserProfile.jsx import { useUser } from '../hooks/useUser'; const UserProfile = ({ userId }) => { const { user, isLoading, loadUser, saveUserChanges } = useUser(); useEffect(() => { loadUser(userId); }, [userId]); if (isLoading) return <div>Loading...</div>; return ( <div className="profile"> <h2>{user.name}</h2> <input value={user.email} onChange={(e) => saveUserChanges({ email: e.target.value })} /> </div> ); };
3. How to structure your project with Hooks?
Forget the old containers/ vs components/ split—feature-based organization is now the recommended approach (especially with Redux Toolkit). Here's a typical structure:
src/ features/ user/ components/ # UI-focused components for the user feature UserProfile.jsx UserList.jsx hooks/ # Custom Hooks for Redux/logic related to this feature useUser.js useUserList.js slices/ # Redux Toolkit slices for state management userSlice.js product/ # Repeat the pattern for other features components/ hooks/ slices/ shared/ # Reusable stuff across features components/ Button.jsx Card.jsx hooks/ useAuth.js
This structure keeps all code related to a feature in one place, making it easier to find, maintain, and refactor.
Quick recap
- Container/presentational separation evolves into logic (Hooks) vs UI (components)
- No more prop injection for Redux—use
useSelector/useDispatchdirectly or via custom Hooks - Organize your project by feature, not by component type
内容的提问来源于stack exchange,提问作者Rahul Yadav

