函数式组件中实现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对象,进而对子组件进 ...
随机推荐
- VC++ 启用内存泄露检测
_CrtDumpMemoryLeaks()就是检测从程序开始到执行该函数进程的堆使用情况,通过使用_CrtDumpMemoryLeaks()我们可以进行简单的内存泄露检测. #include &quo ...
- AtCoder Beginner Contest 238 A - F 题解
AtCoder Beginner Contest 238 \(A - F\) 题解 A - Exponential or Quadratic 题意 判断 \(2^n > n^2\)是否成立? S ...
- django入门 01 创建项目
安装django库 pip install django 创建--by 终端 django-admin startproject myproject 通过命令创建的django项目,默认不含templ ...
- 关于obj.class.getResource()和obj.getClass().getClassLoader().getResource()的路径问题
感谢原文作者:yejg1212 原文链接:https://www.cnblogs.com/yejg1212/p/3270152.html 注:格式内容与原文有轻微不同. Java中取资源时,经常用到C ...
- golang 获取当月最后一天日期
now := time.Now() year, month, day := now.Date() //fmt.Println(year, month, day) //2021 September 1 ...
- ArrayList和LinkList的区别
底层实现区别 ArrayList 底层实现就是数组,且ArrayList实现了RandomAccess,表示它能快速随机访问存储的元素,通过下标 index 访问,只是我们需要用 get() 方法的形 ...
- Java中的输入流与输出流
一.流的概念 在Java中,流是从源到目的地的字节的有序序列.Java中有两种基本的流--输入流(InputStream)和输出流(OutputStream). 根据流相对于程序的另一个端点的不同,分 ...
- 简单理解Zookeeper的Leader选举
Leader选举是保证分布式数据一致性的关键所在.Leader选举分为Zookeeper集群初始化启动时选举和Zookeeper集群运行期间Leader重新选举两种情况.在讲解Leader选举前先了解 ...
- 虫师Selenium2+Python_5、自动化测试模型
P138--模块化驱动测试实例 P142--参数化搜索关键字 from selenium import webdriver search_text = ['python','中文','text'] # ...
- SQL 在数据库中查找拥有此列名的所有表
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME='Column' #"Column"为要查询 ...