开启PropTypes校验时函数组件使用mapStateToProps的冲突处理
问题本质
你的组件props实际分为两类:
- 父组件传递的
公开props:prop1、prop2 - Redux通过connect注入的
私有props:prop3
你将两类props都声明为组件必填prop后,父组件感知不到Redux的注入逻辑,自然会认为你漏传了必填的prop3。
合规解决方案
方案1:拆分Props类型(适配TS+PropTypes场景,最推荐)
如果你同时用了TS和PropTypes,拆分Props类型即可:
// 组件内部实际接收的所有props type InnerProps = { prop1: any; prop2: any; prop3: any; } // 对外暴露给父组件的props(排除Redux注入的prop3) type OuterProps = Omit<InnerProps, 'prop3'> const MyComponent = ({ prop1, prop2, prop3 }: InnerProps) => ( <div> {/* 业务逻辑 */} </div> ) // PropTypes按内部所有props声明,解决ESLint报错 MyComponent.propTypes = { prop1: PropTypes.any.isRequired, prop2: PropTypes.any.isRequired, prop3: PropTypes.any.isRequired, } // 导出的时候指定connect返回组件的props类型为OuterProps export default connect<{prop3: any}, {}, OuterProps>(mapStateToProps)(MyComponent)
此时父组件调用时只需要传prop1和prop2,TS不会再报错,ESLint的prop-types校验也完全合规。
方案2:纯PropTypes场景处理
如果没有用TS,只有ESLint的prop-types校验规则,那你可以给注入完成后的高阶组件单独声明对外的propTypes:
// 内部组件的propTypes照常写,解决ESLint报错 MyComponent.propTypes = { prop1: PropTypes.any.isRequired, prop2: PropTypes.any.isRequired, prop3: PropTypes.any.isRequired, } const ConnectedComponent = connect(mapStateToProps)(MyComponent) // 给对外导出的组件声明公开的propTypes ConnectedComponent.propTypes = { prop1: PropTypes.any.isRequired, prop2: PropTypes.any.isRequired, } export default ConnectedComponent
这个方案下,ESLint只会校验基础组件的propTypes完整性,不会校验高阶组件的propTypes,完全符合规则,父组件也不会感知到prop3的存在。
方案3:使用React-Redux的Hooks写法(更简洁的长期方案)
如果你的项目支持React Hooks,直接用useSelector替代connect高阶组件,从根源上避免这个问题:
import { useSelector } from 'react-redux' const MyComponent = ({ prop1, prop2 }) => { // 直接在组件内部取Redux状态,不需要作为props传入,自然不需要声明propTypes const prop3 = useSelector(state => state.area.prop3) return ( <div> {/* 业务逻辑 */} </div> ) } MyComponent.propTypes = { prop1: PropTypes.any.isRequired, prop2: PropTypes.any.isRequired, } export default MyComponent
这个方案不需要处理任何props拆分,是目前React-Redux官方推荐的写法。
内容的提问来源于stack exchange,提问作者noblerare
相关产品推荐
相关产品推荐

