react 根据传入的key动态改变state

本文探讨了在React中如何根据变量动态改变state,详细解释了使用变量作为state key的正确方法,以及遇到input的maxlength属性在type=number时不生效的问题,原因是maxlength仅在特定输入类型下有效。此外,还提到了input的pattern属性及其应用场景。
部署运行你感兴趣的模型镜像

存输入框输入的值

                        <Input
                            placeholder='请输入已绑定手机号'
                            value={inputPhone}
                            float
                            type="number"
                            pattern="[0-9]*"
                            onChange={(event: any) => this.handlerInput(event, 'inputPhone', 11)}/>
    // 输入
    handlerInput = (event: any, key: any, maxlength: number) => {
        let input = event.target.value;
        this.setState({
            [key]: input.length <= maxlength ? input : input.slice(0, maxlength)
        })
    };

知识点:
1、state的key是一个变量

this.setState({
            key: value
        })

这是常见的修改state的表达式,但是如果我们希望,这里的key是一个变量name,那我们应该怎么写呢?直接写this.setState({name: value})?no,这么写的话,实际上表达的意思是将name作为一个字符串来处理的this.setState({'name': value})
正确写法应该是

this.setState({
            [key]: value
        })

这样的写法实际上是用了es6的属性名表达式(基础真重要,将表达式作为对象的属性名

2、input的maxlength属性不起作用
input的type=number时,maxlength不起作用
解决方案:

input.length <= maxlength ? input : input.slice(0, maxlength)

原因:如果 type 的值是 text, email, search, password, tel, 或 url,那么这个属性指明了用户最多可以输入的字符个数(按照Unicode编码方式计数);对于其他类型的输入框,该属性被忽略。
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input

3、input的pattern属性
检查控件值的正则表达式.。pattern必须匹配整个值,而不仅仅是某些子集.。使用title属性来描述帮助用户的模式.。当类型属性的值为text, search, tel, url 或 email时,此属性适用,否则将被忽略。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

这是一个非常经典且高频的问题:**“我明明调用了 `setState`,为什么 UI 没有更新?”** React 的更新机制是基于 **状态引用比较(shallow comparison)** 的。只有当 React 认为状态“真正变化了”,才会触发重新渲染。 --- ## ✅ 根本原因:React 只在“状态发生有效变化”时才重新渲染 ### 📌 React 判断是否更新的逻辑: ```ts if (oldState !== newState) { reRender(); } ``` 注意:这里是 **`!==` 引用比较**,不是内容比较! --- ## 🔍 常见导致 UI 不更新的原因及解决方案 --- ### ❌ 原因 1:直接修改原数组/对象(Mutating State) ```ts const [list, setList] = useState([1, 2, 3]); // ❌ 错误:直接修改原数组 list.push(4); setList(list); // 引用没变,React 认为没变化 → 不更新 ``` #### ✅ 正确做法:返回新引用 ```ts // ✅ 正确:创建新数组 setList([...list, 4]); // 或 setList(list.concat(4)); ``` --- ### ❌ 原因 2:使用了同一个对象引用 ```ts const data = { name: 'John' }; const [user, setUser] = useState(data); // ❌ 错误:虽然改了属性,但引用相同 user.name = 'Jane'; setUser(user); // 不会触发更新 ``` #### ✅ 正确做法:解构生成新对象 ```ts // ✅ 正确 setUser({ ...user, name: 'Jane' }); // 或深拷贝(复杂嵌套) setUser(JSON.parse(JSON.stringify(newUser))); ``` --- ### ❌ 原因 3:`useState` 初始化值是一个函数调用,但返回相同引用 ```ts const getInitialData = () => [1, 2, 3]; // 每次返回同一个数组引用? const [data, setData] = useState(getInitialData()); // 如果 getInitialData 返回的是缓存的同一数组 function getInitialData() { const arr = [1, 2, 3]; return arr; // 每次都是新的?是的!但如果返回全局变量就危险了 } ``` ⚠️ 更危险的情况: ```ts const DEFAULT_LIST = [1, 2, 3]; const [list, setList] = useState(DEFAULT_LIST); // 后面 setList(DEFAULT_LIST); // 总是同一个引用 → 不更新 ``` #### ✅ 解决方案:始终确保传入新引用 ```ts setList([...DEFAULT_LIST]); ``` --- ### ❌ 原因 4:在 `useEffect` 中依赖项未正确设置 ```ts useEffect(() => { loadData(); }, []); // 只执行一次,后续 state 变化不会触发 ``` 如果 `loadData` 设置了 state,但外层依赖没变,就不会再次拉取数据。 #### ✅ 正确写法: ```ts useEffect(() => { loadData(); }, [deps]); // deps 变化时重新执行 ``` --- ### ❌ 原因 5:父组件阻断了更新(`React.memo` + 浅比较) ```ts const Child = React.memo(({ list }) => { return <div>{list.map(i => <span>{i}</span>)}</div>; }); ``` 即使父组件传递了新的 `list`,只要 `list` 是通过 `===` 比较相等(比如引用没变),`Child` 就不会更新。 #### ✅ 解决方法: - 父组件传入新引用:`<Child list={[...data]} />` - 或自定义 `memo` 比较逻辑: ```ts const Child = React.memo(({ list }) => {...}, (prev, next) => { return prev.list.length === next.list.length && prev.list.every((v, i) => v === next.list[i]); }); ``` --- ### ❌ 原因 6:异步操作中闭包捕获旧状态 ```ts function Component() { const [count, setCount] = useState(0); const badHandler = () => { setTimeout(() => { setCount(count + 1); // ⚠️ 这里的 count 是点击时的旧值! }, 1000); }; } ``` 这不是 UI 不更新,而是逻辑错误导致状态滞后。 #### ✅ 正确做法:使用函数式更新 ```ts setCount(prev => prev + 1); ``` --- ## ✅ 如何调试这类问题? ### 1. 打印日志确认 setState 是否被调用 ```ts console.log("Setting state:", newData); setMockListArray(newData); ``` ### 2. 检查新旧引用是否不同 ```ts console.log("Old:", list, "New:", newList, "Same?", list === newList); ``` ### 3. 使用 React DevTools 查看组件是否 re-render ### 4. 给组件加 `key` 强制刷新(临时测试) ```tsx <List key={someId} data={data} /> ``` --- ## ✅ 最佳实践总结 | 场景 | 推荐写法 | |------|----------| | 更新数组 | `[...oldArray]`, `array.concat()` | | 更新对象 | `{...oldObj}`, `Object.assign({}, obj)` | | 复杂嵌套 | `JSON.parse(JSON.stringify(obj))` 或使用 `immer` | | 函数式更新 | `setState(prev => [...prev, newItem])` | | 避免 mutation | 不要 `.push/.splice/.reverse` 直接改原数组 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值