Fix #91: Add Typing connect() Factory Functions section to README#314
Fix #91: Add Typing connect() Factory Functions section to README#314gfgf-brain wants to merge 3 commits into
Conversation
…README - MapStateToPropsFactory + MapDispatchToPropsFactory type signatures - Per-instance reselect memoization via factory pattern - Comparison: implicit vs explicit return type annotation - Full typed component with OwnProps + StateProps + DispatchProps - When-to-use table Closes piotrwitek#91
There was a problem hiding this comment.
Code Review
This pull request adds documentation on typing React-Redux connect() factory functions to the README, along with a new markdown file containing generic factory examples. The reviewer feedback highlights several issues: a redundant horizontal rule separator in the README, duplicate selector evaluations that can be optimized by caching the result in a local variable, missing imports and interface definitions in the code snippets, and an apparently accidental or incorrect scratchpad file (brain_solution_91.md) containing invalid TypeScript generic signatures.
| --- | ||
|
|
| return (state, ownProps) => ({ | ||
| username: selectUser(state, ownProps)?.name ?? 'Unknown', | ||
| isActive: selectUser(state, ownProps)?.active ?? false, | ||
| }); |
There was a problem hiding this comment.
The memoized selector selectUser is called twice with the same arguments in the returned function. Storing the result in a local variable is cleaner and avoids redundant selector evaluations.
| return (state, ownProps) => ({ | |
| username: selectUser(state, ownProps)?.name ?? 'Unknown', | |
| isActive: selectUser(state, ownProps)?.active ?? false, | |
| }); | |
| return (state, ownProps) => { | |
| const user = selectUser(state, ownProps); | |
| return { | |
| username: user?.name ?? 'Unknown', | |
| isActive: user?.active ?? false, | |
| }; | |
| }; |
| interface DispatchProps { | ||
| onUpdate: (name: string) => void; | ||
| onDelete: () => void; | ||
| } |
There was a problem hiding this comment.
The OwnProps interface is used in this code block but is not defined or imported, which will cause compilation errors if a user copies and pastes this snippet. Defining it here makes the example self-contained.
| interface DispatchProps { | |
| onUpdate: (name: string) => void; | |
| onDelete: () => void; | |
| } | |
| interface OwnProps { | |
| userId: string; | |
| } | |
| interface DispatchProps { | |
| onUpdate: (name: string) => void; | |
| onDelete: () => void; | |
| } |
| ```typescript | ||
| import React from 'react'; | ||
| import { connect, MapStateToPropsFactory } from 'react-redux'; | ||
| import { createSelector } from 'reselect'; | ||
|
|
There was a problem hiding this comment.
The Full Typed Component example is missing imports for Dispatch (from redux) and deleteUser (from actions), as well as the definition for RootState. Adding these makes the example fully compilable and copy-paste friendly.
| ```typescript | |
| import React from 'react'; | |
| import { connect, MapStateToPropsFactory } from 'react-redux'; | |
| import { createSelector } from 'reselect'; | |
| import React from 'react'; | |
| import { Dispatch } from 'redux'; | |
| import { connect, MapStateToPropsFactory } from 'react-redux'; | |
| import { createSelector } from 'reselect'; | |
| import { deleteUser } from './actions'; | |
| interface RootState { | |
| users: Record<string, { name: string; active: boolean }>; | |
| } |
| return (state, ownProps) => ({ | ||
| username: sel(state, ownProps)?.name ?? 'Unknown', | ||
| isActive: sel(state, ownProps)?.active ?? false, | ||
| }); |
There was a problem hiding this comment.
The memoized selector sel is called twice with the same arguments. Storing the result in a local variable is cleaner and avoids redundant evaluations.
| return (state, ownProps) => ({ | |
| username: sel(state, ownProps)?.name ?? 'Unknown', | |
| isActive: sel(state, ownProps)?.active ?? false, | |
| }); | |
| return (state, ownProps) => { | |
| const user = sel(state, ownProps); | |
| return { | |
| username: user?.name ?? 'Unknown', | |
| isActive: user?.active ?? false, | |
| }; | |
| }; |
| ```markdown | ||
| <!-- Brain solution for: Factory types for connect props | ||
| <!-- Approach: Implementing factory types for connect props using TypeScript generics and type inference. --> |
There was a problem hiding this comment.
This file (brain_solution_91.md) appears to be an accidental commit or a temporary scratchpad, as it is not mentioned in the pull request description or the README changes. Additionally, the TypeScript examples inside it contain incorrect generic signatures (e.g., returning generic functions <S, O> which are incompatible with MapStateToPropsFactory and will fail to compile against selectors expecting concrete types). If this file is not intended to be part of the repository, please delete it.
… remove scratchpad - Remove redundant --- separator - Cache selectUser/sel in const user (avoid double memoized selector call) - Add OwnProps interface to make snippet self-contained - Full Typed Component: add Dispatch, deleteUser, RootState imports - Delete brain_solution_91.md
|
Addressed all review feedback in commit 4d6e454. |
Closes #91
Changes
Adds a Typing connect() Factory Functions section to
README.mdcovering:MapStateToPropsFactory<StateProps, OwnProps, RootState>— factory for per-instance memoizedmapStateToPropsMapDispatchToPropsFactory<DispatchProps, OwnProps>— factory for per-instancemapDispatchToPropsreselectselector that prevents cache invalidation across list itemsOwnProps & StateProps & DispatchPropsmapStateToPropsvs factory formTesting
react-reduxandreselecttypesMapStateToPropsFactoryprevents the confusinganyreturn type error