使用Recompose时如何用本地属性覆盖Redux映射的errorText属性?
解决Redux与本地验证错误文本冲突的问题
我懂你现在遇到的麻烦:提交请求失败后Redux返回的错误会占据errorText,但用户再次编辑手机号时,本地验证生成的错误根本盖不掉这个Redux里的错误文本,而且你还不想改现有的变量名。
核心问题出在你的compose增强链里——connect和withState都在用errorText这个属性名,导致两者的状态互相覆盖,没法按照你想要的优先级展示错误。下面是不用修改变量名的解决方案:
解决方案:分离状态并按优先级合并
我们可以把Redux的错误和本地验证的错误分开存储,再通过withProps按照本地验证错误优先的逻辑合并成原来的errorText属性,组件里的代码完全不用动:
const enhance = compose( withHandlers({ changePhoneInput, submitPhone }), withState('phone', 'setPhone', ''), // 1. 将Redux的错误映射为临时属性,避免和本地状态重名 connect((state, nextOwnProps) => { state = state.get('settings') return { loading: state.get('loading'), reduxError: state.get('error') // 这里临时换个名字,不影响组件最终使用 } }, { submitPhoneAction }), // 2. 保留本地验证的错误状态,setErrorText名字不变(和原changePhoneInput兼容) withState('localErrorText', 'setErrorText', ''), // 3. 合并成原有的errorText:本地错误优先,无本地错误时显示Redux错误 withProps(({ reduxError, localErrorText }) => ({ errorText: localErrorText || reduxError })) )
方案为什么有效:
changePhoneInput函数里的setErrorText依然作用于本地的localErrorText,这个函数的代码完全不用改- 组件接收的
errorText是合并后的结果:用户输入手机号时,本地验证的错误会优先显示;用户没输入(比如提交失败后还没编辑)时,才会显示Redux返回的错误 - 组件的
render代码完全不需要调整,errorText变量名保持原样
可选优化:
如果你希望用户一开始输入就清空Redux里的错误,可以在changePhoneInput里加一个清除Redux错误的action:
const changePhoneInput = props => phone => { const { setPhone, setErrorText, clearReduxError } = props setPhone(phone) let error = /[0-9]{6,9}/g.test(phone) ? '' : "Please enter valid number"; setErrorText(error) // 清空Redux中的错误状态 clearReduxError() };
记得在connect的第二个参数里引入对应的清除错误action即可。
内容的提问来源于stack exchange,提问作者Ilja
相关产品推荐
相关产品推荐

