React组件中被解构props的默认值设置会产生什么效果?
首先得明确一点:你在defaultProps里设置的rest: {}以及propTypes里的rest: PropTypes.object其实都是无效的,咱们一步步拆解原因和实际效果:
rest并不是一个实际接收的props
你这里的const { css, ...rest } = props是ES6的剩余属性解构,意思是把props里除了css之外的所有其他属性收集到rest这个对象里。用户使用SpecialButton时,不会传递一个叫rest的props(比如<SpecialButton rest={{ onClick: () => {} }} />),而是直接传<SpecialButton onClick={() => {}} disabled />这类属性,这些属性会自动被归到rest里。而
defaultProps是用来给明确声明的单个props设置默认值的,比如你给css设置''是有效的,因为css是你明确从props里解构出来的props。但rest不是一个用户会传递的props,所以defaultProps.rest = {}这个设置完全不会生效。rest的天然默认值就是空对象
当用户没有传递任何除css之外的props时,...rest解构出来的结果本身就是空对象{},这是ES6解构的默认行为。所以你手动设置的rest: {}完全是多余的,有没有它,rest都会在没有剩余props时变成空对象。propTypes里的rest校验也无效
和上面的原因一样,用户不会传递rest这个props,所以PropTypes.object的校验永远不会触发。如果想对透传给Button的props做校验,正确的做法是要么让Button自己处理它的propTypes(因为你已经把...rest传给它了),要么使用自定义的propTypes校验函数来检查所有非css的props。
修正后的代码示例
const SpecialButton = (props) => { const { css, ...rest } = props; return ( <Button className={`special-btn ${css}`} {...rest} > Click here </Button> ); }; // 只保留有效默认值 SpecialButton.defaultProps = { css: '' }; // 只校验实际接收的props SpecialButton.propTypes = { css: PropTypes.string };
这样写就足够了,rest会自动在没有额外props时成为空对象,透传给Button也不会有问题。
内容的提问来源于stack exchange,提问作者Rafael Rozon

