大家好,我是小十七_,今天一起来看一个 taro 表单组件的问题,taro input onInput 值不更新的原因,表单组件不是受控组件
遇到的问题
一天,产品提了一个很简单的需求,一个输入框只能输入字母,本来以为 input 肯定是受控组件,分分钟搞定,没想到搞了半天
代码是这样的:
import React, { useState } from 'react';
import { Input } from '@tarojs/components';
export default function Test() {
const [value, setValue] = useState('');
const handleInput = e => {
setValue(e.detail.value.replace(/[^a-zA-Z]/g, ''));
};
return <Input value={value} onInput={handleInput} maxlength={6} />;
}
本来以为这就结束了,结果测试后,没有生效
- 输入 a,显示 a
- 输入 a1,显示 a1
可以发现 input 不是一个受控组件,输入 a1 后,我们在 onInput 中改了 state 中的 value 为 a,并没有更新到 input 中。
原因 & 解决方式
参考这个回答:github.com/NervJS/taro…
微信小程序中表单组件不是完全受控的,Input 组件输入后,视图立即变化,但其 value 绑定的值还是旧值,这时你直接 setState 一个旧值会被 Taro 的 diff 过滤掉。
发现 Taro 的 官方文档 已经写了这个问题,和一些其他问题的解决方法
具体的过程是: 输入 a。 视图显示 a。 onInput 逻辑处理后 setState({ val: 'a' }) taro diff('a', '') setData({ val: 'a' })
输入 1。 视图显示 a1。 onInput 逻辑处理后 setState({ val: 'a' }) taro diff('a', 'a') 不去 setData
解决的办法在于视图改变时,立即同步 data,把值改成新值,然后再对 data 值进行进一步修改。
const handleInput = e => {
setValue(e.detail.value);
setTimeout(() => setValue(e.detail.value.replace(/[^a-zA-Z]/g, '')))
};