CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-redux

Official React bindings for Redux state management with hooks and higher-order components

Pending
Overview
Eval results
Files

connect.mddocs/

Connect Higher-Order Component

Legacy API for connecting React components to Redux store using higher-order component pattern. While hooks are the recommended modern approach, connect remains fully supported for class components and complex scenarios.

Capabilities

Connect Function

Higher-order component factory that connects React components to Redux store by injecting state and dispatch as props.

/**
 * Connect function overloads for different usage patterns
 */
interface Connect<DefaultState = unknown> {
  // No arguments - just adds dispatch prop
  (): InferableComponentEnhancer<DispatchProp>;
  
  // mapStateToProps only  
  <TStateProps = {}, no_dispatch = {}, TOwnProps = {}, State = DefaultState>(
    mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>
  ): InferableComponentEnhancerWithProps<TStateProps & DispatchProp, TOwnProps>;
  
  // mapDispatchToProps only (function)
  <no_state = {}, TDispatchProps = {}, TOwnProps = {}>(
    mapStateToProps: null | undefined,
    mapDispatchToProps: MapDispatchToPropsFunction<TDispatchProps, TOwnProps>
  ): InferableComponentEnhancerWithProps<TDispatchProps, TOwnProps>;
  
  // mapDispatchToProps only (object)  
  <no_state = {}, TDispatchProps = {}, TOwnProps = {}>(
    mapStateToProps: null | undefined,
    mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
  ): InferableComponentEnhancerWithProps<ResolveThunks<TDispatchProps>, TOwnProps>;
  
  // Both mapStateToProps and mapDispatchToProps (function)
  <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, State = DefaultState>(
    mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
    mapDispatchToProps: MapDispatchToPropsFunction<TDispatchProps, TOwnProps>
  ): InferableComponentEnhancerWithProps<TStateProps & TDispatchProps, TOwnProps>;
  
  // Both mapStateToProps and mapDispatchToProps (object)
  <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, State = DefaultState>(
    mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
    mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>
  ): InferableComponentEnhancerWithProps<TStateProps & ResolveThunks<TDispatchProps>, TOwnProps>;
  
  // All three arguments
  <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, TMergedProps = {}, State = DefaultState>(
    mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
    mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
    mergeProps: MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps>
  ): InferableComponentEnhancerWithProps<TMergedProps, TOwnProps>;
  
  // All four arguments
  <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, TMergedProps = {}, State = DefaultState>(
    mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
    mapDispatchToProps: MapDispatchToPropsParam<TDispatchProps, TOwnProps>,
    mergeProps: MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps>,
    options: ConnectOptions<State, TStateProps, TOwnProps, TMergedProps>
  ): InferableComponentEnhancerWithProps<TMergedProps, TOwnProps>;
}

const connect: Connect;

type InferableComponentEnhancer<TInjectedProps> = 
  InferableComponentEnhancerWithProps<TInjectedProps, {}>;

type InferableComponentEnhancerWithProps<TInjectedProps, TNeedsProps> = 
  <C extends ComponentType<Matching<TInjectedProps, GetProps<C>>>>(
    component: C
  ) => ConnectedComponent<C, Mapped<DistributiveOmit<GetLibraryManagedProps<C>, keyof Shared<TInjectedProps, GetLibraryManagedProps<C>>> & TNeedsProps & ConnectPropsMaybeWithoutContext<TNeedsProps & GetProps<C>>>>;

type ConnectedComponent<C extends ComponentType<any>, P> = 
  FunctionComponent<P> & NonReactStatics<C> & { WrappedComponent: C };

Basic Usage:

import { connect } from "react-redux";

// Class component
class TodoList extends Component<Props> {
  render() {
    const { todos, addTodo } = this.props;
    return (
      <div>
        {todos.map(todo => <div key={todo.id}>{todo.text}</div>)}
        <button onClick={() => addTodo("New todo")}>Add</button>
      </div>
    );
  }
}

// Connect to Redux
const mapStateToProps = (state: RootState) => ({
  todos: state.todos
});

const mapDispatchToProps = {
  addTodo: (text: string) => ({ type: "ADD_TODO", payload: text })
};

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

Map State to Props

Functions that define how Redux state maps to component props.

/**
 * Function that maps Redux state to component props
 */
type MapStateToProps<TStateProps, TOwnProps, State> = 
  (state: State, ownProps: TOwnProps) => TStateProps;

/**
 * Factory function that creates a mapStateToProps function
 */
type MapStateToPropsFactory<TStateProps, TOwnProps, State> = 
  (initialState: State, ownProps: TOwnProps) => MapStateToProps<TStateProps, TOwnProps, State>;

/**
 * Parameter type for mapStateToProps - can be function or factory
 */
type MapStateToPropsParam<TStateProps, TOwnProps, State> = 
  MapStateToPropsFactory<TStateProps, TOwnProps, State> | 
  MapStateToProps<TStateProps, TOwnProps, State> | 
  null | 
  undefined;

Usage Examples:

// Simple state mapping
const mapStateToProps = (state: RootState) => ({
  user: state.auth.user,
  isLoading: state.ui.loading
});

// With own props
const mapStateToProps = (state: RootState, ownProps: OwnProps) => ({
  todo: state.todos.find(todo => todo.id === ownProps.todoId)
});

// Factory function for performance optimization
const makeMapStateToProps = () => {
  const getTodosForUser = createSelector(
    [(state: RootState) => state.todos, (state: RootState, props: Props) => props.userId],
    (todos, userId) => todos.filter(todo => todo.userId === userId)
  );
  
  return (state: RootState, props: Props) => ({
    todos: getTodosForUser(state, props)
  });
};

Map Dispatch to Props

Functions and objects that define how dispatch maps to component props.

/**
 * Function that maps dispatch to component props
 */
type MapDispatchToPropsFunction<TDispatchProps, TOwnProps> = 
  (dispatch: Dispatch<Action<string>>, ownProps: TOwnProps) => TDispatchProps;

/**
 * Object mapping action creators to component props
 */
type MapDispatchToProps<TDispatchProps, TOwnProps> = 
  MapDispatchToPropsFunction<TDispatchProps, TOwnProps> | TDispatchProps;

/**
 * Factory function that creates a mapDispatchToProps function
 */
type MapDispatchToPropsFactory<TDispatchProps, TOwnProps> = 
  (dispatch: Dispatch<Action<string>>, ownProps: TOwnProps) => MapDispatchToPropsFunction<TDispatchProps, TOwnProps>;

/**
 * Parameter type for mapDispatchToProps
 */
type MapDispatchToPropsParam<TDispatchProps, TOwnProps> = 
  MapDispatchToPropsFactory<TDispatchProps, TOwnProps> | 
  MapDispatchToProps<TDispatchProps, TOwnProps>;

/**
 * Resolves thunk action creators in dispatch props
 */
type ResolveThunks<TDispatchProps> = TDispatchProps extends { [key: string]: any }
  ? { [C in keyof TDispatchProps]: HandleThunkActionCreator<TDispatchProps[C]> }
  : TDispatchProps;

Usage Examples:

// Object shorthand (recommended)
const mapDispatchToProps = {
  addTodo: (text: string) => ({ type: "ADD_TODO", payload: text }),
  removeTodo: (id: number) => ({ type: "REMOVE_TODO", payload: id })
};

// Function form
const mapDispatchToProps = (dispatch: Dispatch) => ({
  addTodo: (text: string) => dispatch({ type: "ADD_TODO", payload: text }),
  removeTodo: (id: number) => dispatch({ type: "REMOVE_TODO", payload: id })
});

// With thunk actions
const mapDispatchToProps = {
  fetchUser: fetchUserThunk,
  updateUser: updateUserThunk
};

// Factory function
const makeMapDispatchToProps = () => {
  return (dispatch: Dispatch, ownProps: Props) => ({
    loadData: () => dispatch(fetchData(ownProps.dataId))
  });
};

Merge Props

Function that combines state props, dispatch props, and own props into final props.

/**
 * Function that merges state props, dispatch props, and own props
 * @param stateProps - Props from mapStateToProps
 * @param dispatchProps - Props from mapDispatchToProps
 * @param ownProps - Props passed to the connected component
 * @returns Final props object for the wrapped component
 */
type MergeProps<TStateProps, TDispatchProps, TOwnProps, TMergedProps> = 
  (stateProps: TStateProps, dispatchProps: TDispatchProps, ownProps: TOwnProps) => TMergedProps;

Usage Example:

const mergeProps = (stateProps, dispatchProps, ownProps) => ({
  ...stateProps,
  ...dispatchProps,
  ...ownProps,
  // Custom merged prop
  canEdit: stateProps.user.id === ownProps.itemOwnerId && stateProps.user.isLoggedIn
});

const ConnectedComponent = connect(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps
)(MyComponent);

Connect Options

Configuration options for customizing connect behavior.

interface ConnectOptions<State = unknown, TStateProps = {}, TOwnProps = {}, TMergedProps = {}> {
  /** Enable ref forwarding to wrapped component */
  forwardRef?: boolean;
  /** Custom context to use instead of ReactReduxContext */
  context?: typeof ReactReduxContext;
  /** Custom equality function for state comparison */
  areStatesEqual?: (nextState: State, prevState: State, nextOwnProps: TOwnProps, prevOwnProps: TOwnProps) => boolean;
  /** Custom equality function for own props comparison */
  areOwnPropsEqual?: (nextOwnProps: TOwnProps, prevOwnProps: TOwnProps) => boolean;
  /** Custom equality function for state props comparison */
  areStatePropsEqual?: (nextStateProps: TStateProps, prevStateProps: TStateProps) => boolean;
  /** Custom equality function for merged props comparison */
  areMergedPropsEqual?: (nextMergedProps: TMergedProps, prevMergedProps: TMergedProps) => boolean;
}

Usage Example:

const options = {
  forwardRef: true,
  areStatesEqual: (next, prev) => next.version === prev.version,
  areOwnPropsEqual: (next, prev) => next.id === prev.id
};

const ConnectedComponent = connect(
  mapStateToProps,
  mapDispatchToProps,
  null,
  options
)(MyComponent);

// Access original component through ref
const ref = useRef();
<ConnectedComponent ref={ref} />
// ref.current points to MyComponent instance

Advanced Usage

ConnectedProps Type Helper

Extract props type from a connected component for type reuse.

/**
 * Extracts the props type from a connected component
 */
type ConnectedProps<TConnector> = TConnector extends InferableComponentEnhancerWithProps<infer TInjectedProps, any>
  ? unknown extends TInjectedProps
    ? TConnector extends InferableComponentEnhancer<infer TInjectedProps>
      ? TInjectedProps  
      : never
    : TInjectedProps
  : never;

Usage Example:

const connector = connect(mapStateToProps, mapDispatchToProps);
type PropsFromRedux = ConnectedProps<typeof connector>;

// Use in component definition
const MyComponent: React.FC<PropsFromRedux & OwnProps> = (props) => {
  // props includes both Redux and own props
};

export default connector(MyComponent);

Custom Context Usage

Use connect with custom React context for multiple stores.

import { createContext } from "react";
import { connect } from "react-redux";

const CustomContext = createContext(null);

const ConnectedComponent = connect(
  mapStateToProps,
  mapDispatchToProps,
  null,
  { context: CustomContext }
)(MyComponent);

// Provide custom context
<Provider store={customStore} context={CustomContext}>
  <ConnectedComponent />
</Provider>

Migration from Connect to Hooks

While connect is fully supported, hooks provide a more modern and flexible API:

// Connect approach
const mapStateToProps = (state: RootState) => ({
  todos: state.todos,
  user: state.user
});

const mapDispatchToProps = {
  addTodo,
  removeUser
};

export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

// Hooks approach
function TodoList() {
  const todos = useSelector((state: RootState) => state.todos);
  const user = useSelector((state: RootState) => state.user);
  const dispatch = useDispatch();

  const handleAddTodo = (text: string) => dispatch(addTodo(text));
  const handleRemoveUser = (id: number) => dispatch(removeUser(id));

  return (
    // Component JSX
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-react-redux

docs

connect.md

hooks.md

index.md

typescript.md

tile.json