React Redux v9 - `connect`
React Redux v9: Why connect() Shows a Deprecated Warning and How to Fix It
If you've recently upgraded to React Redux v9 and are using IntelliJ, VS Code, or another TypeScript-aware IDE, you may have noticed a warning when hovering over connect():
@deprecated
We recommend using the useSelector and useDispatch hooks instead.
See https://react-redux.js.org/api/hooks
If you need to use connect without this visual deprecation warning,
import legacy_connect instead:
import { legacy_connect as connect } from 'react-redux'
This can be surprising, especially because many existing React applications still use connect() extensively.
Let's understand what's happening and explore the available options.
Is connect() Actually Deprecated?
Not exactly.
React Redux v9 adds a TypeScript/JSDoc deprecation annotation to encourage developers to adopt the modern Hooks API:
useSelector()useDispatch()
However, connect() still works and remains supported.
The warning is primarily intended to guide developers toward the recommended pattern for function components.
Example: Existing connect() Implementation
Many applications use a pattern similar to this:
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import { connect } from 'react-redux';
const ForgotPassword = ({ auth }) => {
const navigate = useNavigate();
useEffect(() => {
if (auth.loggedIn) {
navigate('/dashboard');
}
}, [auth.loggedIn, navigate]);
return <div>Forgot Password</div>;
};
const mapState = (state) => ({
auth: state.auth,
});
export default connect(mapState)(ForgotPassword);
This code is completely valid and will continue to work.
The only issue is the IDE warning.
Option 1: Migrate to Hooks (Recommended)
For function components, React Redux recommends using hooks instead of connect().
Before
export default connect(mapState)(ForgotPassword);
After
import { useSelector } from 'react-redux';
const ForgotPassword = () => {
const auth = useSelector((state) => state.auth);
return <div>Forgot Password</div>;
};
export default ForgotPassword;
A more complete example:
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
const ForgotPassword = () => {
const navigate = useNavigate();
const auth = useSelector((state) => state.auth);
useEffect(() => {
if (auth.loggedIn) {
navigate('/dashboard');
}
}, [auth.loggedIn, navigate]);
return <div>Forgot Password</div>;
};
export default ForgotPassword;
Benefits
- Less boilerplate
- No
mapStateToProps - Better TypeScript support
- Officially recommended by React Redux
Option 2: Continue Using connect()
If your application already contains many connected components, there is no immediate need to refactor everything.
You can simply keep using:
import { connect } from 'react-redux';
The warning is informational and does not affect runtime behavior.
This approach is often preferred in mature enterprise applications where consistency is more important than adopting the latest syntax.
Option 3: Use legacy_connect
React Redux v9 introduces a special alias called legacy_connect.
Replace:
import { connect } from 'react-redux';
with:
import { legacy_connect as connect } from 'react-redux';
The rest of your code remains unchanged:
const mapState = (state) => ({
auth: state.auth,
});
export default connect(mapState)(ForgotPassword);
Why Use legacy_connect?
- Removes IDE deprecation warnings
- No behavior changes
- No refactoring required
- Useful for large existing codebases
Recommended Approach for Different Scenarios
New Projects
Use hooks:
useSelector()
useDispatch()
This is the modern React Redux pattern.
Existing Applications
If your project already contains dozens or hundreds of connected components:
import { legacy_connect as connect } from 'react-redux';
can be a practical intermediate solution.
Gradual Migration Strategy
Many teams adopt the following approach:
- Keep existing
connect()components. - Use hooks for all new components.
- Gradually migrate old components when they are modified.
- Use
legacy_connectto suppress warnings during the transition.
This avoids large-scale refactoring while moving toward modern React Redux patterns.
TypeScript Bonus: Typed Hooks
For Redux Toolkit applications, consider creating typed hooks.
// store.ts
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
// hooks.ts
import { useDispatch, useSelector } from 'react-redux';
export const useAppDispatch =
useDispatch.withTypes<AppDispatch>();
export const useAppSelector =
useSelector.withTypes<RootState>();
Usage:
const auth = useAppSelector((state) => state.auth);
This provides stronger type safety and a better developer experience.
Conclusion
The connect() warning in React Redux v9 is not an indication that the API has been removed. It is a recommendation from the React Redux team to use the Hooks API in modern React applications.
You can choose one of three paths:
- Best for new code:
useSelector()anduseDispatch() - Best for existing code: continue using
connect() - Best for removing warnings without refactoring:
legacy_connect
For most teams, a gradual migration strategy offers the best balance between modernizing the codebase and minimizing risk.