函数式组件中实现Antd打开Modal后其Input框自动聚焦(focus)到文字的最后
目前React使用函数式组件已经成为趋势, 如何把React函数式组件用好, 提高性能, 从而实现业务需求也成为了一种能力的体现......咳咳咳, 进入正题:
现实场景需求
我想实现这一个需求, 父组件收到文字消息后将其传送给子组件, 子组件是一个Antd组件中的Modal, 里面只有一个input输入框, 子组件收到父组件传过来的文字消息后打开Modal对话框, 其input输入框中的默认值为父组件传递过来的文字消息, 并且自动focus到文字消息的最后, 从而方便用户输入, 当输入完之后, 点击确定按钮调用函数再把消息发送回去.
遇到的问题
怎么说呢, 我本来是打算使用一个给input输入框一个ref(inputRef), 然后当modal框打开时, 使用useEffect副作用钩子, 然后通过使用inputRef的foucs函数来实现自动聚焦, 然而想象是美好的, 现实是残酷的, 如果这么容易能解决我就不会写博客了, 先上错误代码:
import React, { useRef, useEffect } from 'react'
import { Input, Modal } from 'antd'
// 引入useSelector用于读取redux store中保存的数据, 引入useDispath用于分发数据
import { useSelector, useDispatch } from "react-redux"
// 引入action
import { change_input_modal_visible } from "../../redux/actions/visible"
const { TextArea } = Input
// props 传递过来的是发送消息的函数和文本编辑框已有的内容textContent
export default function InputModal(props) {
const inputRef = useRef()
// store dispatch
const dispatch = useDispatch()
// store里保存的数据, 来控制modal是否显示, 父组件收到文本框编辑消息后会改为true, 从而显示modal对话框
const inputModalVisible = useSelector(state => state.visible.inputModalVisible)
// 如果inputModalVisible为true, 聚焦input框
useEffect(() => {
if(inputModalVisible) {
inputRef.current.focus({
cursor: 'end'
})
}
}, [inputModalVisible, inputRef])
const handleOk = () => {
let textValue = inputRef.current.resizableTextArea.props.value
console.log(textValue)
// 去除前后多余的空格
let res = textValue.trim()
// 如果内容不为空才发送给UE4程序, 具体发送逻辑省略
// 将modal对话框关闭
dispatch(change_input_modal_visible(false));
};
// 取消发送消息
const handleCancel = () => {
// 将modal对话框关闭
dispatch(change_input_modal_visible(false));
};
return (
<div className='modal_wrapper'>
<Modal
centered
closable={false}
destroyOnClose
title={null}
visible={inputModalVisible}
onOk={handleOk}
onCancel={handleCancel}
cancelText="取消"
okText="确定"
>
<TextArea
showCount
maxLength={100}
placeholder="请输入内容"
allowClear
defaultValue={props.textContent}
ref={inputRef}
/>
</Modal>
</div>
)
}
但是bug随之就来了:

原因是在Modal框的visible为false时, 网页上根本不会加载Modal节点, 当然就获取不到inputRef, inputRef.current的结果就为null, 下图第一张图为Modal框的visible为false时的DOM树, 第二张图为Modal框的visible为true时的DOM树:

Modal框的visible为false时的DOM树

Modal框的visible为true时的DOM树
既然问题找到了, 那就提一下我目前的解决办法吧!
解决办法
我的解决办法是利用ref的原理, 当input输入框挂载时, 使用ref进行聚焦, 关键代码片段如下:
<TextArea
ref={(input) => {
if (input != null) {
input.focus({
cursor: 'end'
});
}
}}
>
但是随之还有一个问题, 我现在ref用来进行聚焦了, 我如何拿到input输入框内的值呢? 我还要输入框消息发送回去呢! 还好Input输入框还有一个onChange函数, 我可以用这个来维护一个state来保存在state中, 既然思路有了, 就上一下源代码:
import React, { useState, useEffect } from 'react'
import { Input, Modal } from 'antd'
// 引入useSelector用于读取redux store中保存的数据, 引入useDispath用于分发数据
import { useSelector, useDispatch } from "react-redux"
// 引入action
import { change_input_modal_visible } from "../../redux/actions/visible"
const { TextArea } = Input
// props 传递过来的是发送消息的函数和UE4中文本编辑框已有的内容textContent
export default function InputModal(props) {
// 在state中保存目前输入框内的内容, 初始化为空字符串
const [textValue, setTextValue] = useState('')
// store dispatch
const dispatch = useDispatch()
// store里保存的数据, 来控制modal是否显示, 父组件收到文本框编辑消息后会改为true, 从而显示modal对话框
const inputModalVisible = useSelector(state => state.visible.inputModalVisible)
// 当props中textContent发生变化时, 即收到文本编辑框内容消息更新之后
// 同步更新保存在textValue中
useEffect(() => {
setTextValue(props.textContent)
}, [props.textContent])
const handleOk = () => {
// 发送消息
console.log(textValue)
// 去除前后多余的空格
let res = textValue.trim()
// 如果内容不为空才发送给UE4程序, 具体发送逻辑不再展示
// 将modal对话框关闭
dispatch(change_input_modal_visible(false));
};
// 取消发送消息
const handleCancel = () => {
// 将modal对话框关闭
dispatch(change_input_modal_visible(false));
};
const handleChange = e => {
// 当输入框内容发生变化时, 同步给textValue
setTextValue(e.target.value)
}
return (
<>
<Modal
centered
closable={false}
destroyOnClose
title={null}
visible={inputModalVisible}
onOk={handleOk}
onCancel={handleCancel}
cancelText="取消"
okText="确定"
>
<TextArea
showCount
maxLength={100}
placeholder="请输入内容"
allowClear
defaultValue={props.textContent}
ref={(input) => {
if (input != null) {
input.focus({
cursor: 'end'
});
}
}}
onChange={handleChange}
/>
</Modal>
</>
)
}
结语
至此, 本篇结束, 如果大家有更好的方法, 希望大家提出来, 或者有不懂的也可以留言, 感谢!
函数式组件中实现Antd打开Modal后其Input框自动聚焦(focus)到文字的最后的更多相关文章
- Visual Studio 打开解决方案后 弹出框显示 "正在打开文件..." 迟迟没反应 的解决方法
Visual Studio 打开解决方案后 弹出框显示 "正在打开文件...",任务管理器的devenv进程又很正常,不会显示"未响应". 而IDE的左下角有个 ...
- vue组件中,iview的modal组件爬坑--modal的显示与否应该是使用v-show
这是我第一次写博客,主要是记录下自己解决问题的过程和知识的总结,如有不对的地方欢迎指出来! 需求:点击btn,弹出modal显示图表(以折现图为例) 这应该是很基本的需求也是很容易实现的,代码和效果如 ...
- vue中让input框自动聚焦
created(){ this.changfouce(); }, methods: { //在vue生命周期的created()钩子函数进行的DOM操作要放在Vue.nextTick()的回调函数中, ...
- 去除 chrome 上保存密码后的 input 框的屎黄色背景
网上找的设置 background-color,background-image 没用,后来找到这个方法测试有效: input:-webkit-autofill { transition: backg ...
- radio后的input框数据传递
<input type="radio" name="limit_type" value="total">活动期间,每个手机号可抽 ...
- React函数式组件和类组件[Dan]
一篇对Dan的 How Are Function Components Different from Classes? 一文的个人阅读总结,内容来自于此.强烈推荐阅读 Dan Abramov.的博客. ...
- react项目中使用antd
1.antd官网: https://ant.design/docs/react/introduce-cn 2.React中使用Antd 1.安装antd npm install antd --save ...
- react+dva 全局model中异步获取数据state在组件中取不到值
先上结论,不是取不到,是写法有问题. 全文分4部分,1是问题描述,2是一开始的解决想法(错误做法),3是问题产生原因的思考,4是正常解决方法.只想看结论直接跳4 1.问题描述 接触react dva一 ...
- React函数式组件使用Ref
目录: 简介 useRef forwardRef useImperativeHandle 回调Ref 简介 大家都知道React中的ref属性可以帮助我们获取子组件的实例或者Dom对象,进而对子组件进 ...
随机推荐
- Heartbeat部署
部署环境:CentOS 7 1.Heartbeat介绍 Heartbeat是Linux-HA项目中的一个组件,它实现了一个高可用集群系统.心跳检测和集群通信是高可用的两个关键组件,在Heartbeat ...
- Spring系列13:bean的生命周期
本文内容 bean的完整的生命周期 生命周期回调接口 Aware接口详解 Spring Bean的生命周期 面试热题:请描述下Spring的生命周期? 4大生命周期 从源码角度来说,简单分为4大阶段: ...
- SendMessage 键值
转载请注明来源:https://www.cnblogs.com/hookjc/ SendMessage(hWnd,WM_SETFOCUS,0,0); SendMessage(hWnd,WM_ACTIV ...
- 用curl发起https请求
使用curl发起https请求 使用curl如果想发起的https请求正常的话有2种做法: 方法一.设定为不验证证书和host. 在执行curl_exec()之前.设置option $ch = cur ...
- C#中的字符串拼接@,$
转载自:https://blog.csdn.net/qq_40666620/article/details/101695138 一:@ @的意思是以@标注的字符出,其中所有的符号均为字符串符号,没有什 ...
- iOS 模糊、精确搜索匹配功能方法总结 By HL
字符串搜索主要用于UITableView的搜索功能的筛选,过滤,查询 下面是一些流行的搜索查询方法 一.遍历搜索 for循环 根据要求:精确搜索(判读字符串相等) 模糊搜索(字符串包含) 相关知识 ...
- 一键部署lnmp
一键部署lnmp 提前将nginx .mysql .php 所需安装包都放在/opt目录下 脚本启动结束时,重启一下nginx 服务,就能在火狐浏览器更新出php测试页 脚本如下:(脚本里的软件 ...
- Java访问修饰符和三大特征(封装,继承和多态)
一.访问修饰符基本介绍: java提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围): 1.公开级别:用public修饰,对外公开2.受保护级别:用protected修饰,对子 ...
- 海康PTZ云台摄像头调试之直接控制云台(C#)
众所周知,海康的摄像头sdk较为完善,但是对于新手来说还是有点麻烦. 今天写一篇随笔给大家展示下怎么控制海康摄像头的云台(前提是有ptz云台设备) 1.sdk准备 本文基于C#的frame来开发一个p ...
- netty系列之:让TCP连接快一点,再快一点
简介 经典的TCP三次握手大家应该很熟悉了,三次握手按道理说应该是最优的方案了,当然这是对于通用的情况来说的.那么在某些特殊的情况下是不是可以提升TCP建立连接的速度呢? 答案是肯定的,这就是今天我们 ...