目前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)到文字的最后的更多相关文章

  1. Visual Studio 打开解决方案后 弹出框显示 "正在打开文件..." 迟迟没反应 的解决方法

    Visual Studio 打开解决方案后 弹出框显示 "正在打开文件...",任务管理器的devenv进程又很正常,不会显示"未响应". 而IDE的左下角有个 ...

  2. vue组件中,iview的modal组件爬坑--modal的显示与否应该是使用v-show

    这是我第一次写博客,主要是记录下自己解决问题的过程和知识的总结,如有不对的地方欢迎指出来! 需求:点击btn,弹出modal显示图表(以折现图为例) 这应该是很基本的需求也是很容易实现的,代码和效果如 ...

  3. vue中让input框自动聚焦

    created(){ this.changfouce(); }, methods: { //在vue生命周期的created()钩子函数进行的DOM操作要放在Vue.nextTick()的回调函数中, ...

  4. 去除 chrome 上保存密码后的 input 框的屎黄色背景

    网上找的设置 background-color,background-image 没用,后来找到这个方法测试有效: input:-webkit-autofill { transition: backg ...

  5. radio后的input框数据传递

    <input type="radio" name="limit_type" value="total">活动期间,每个手机号可抽 ...

  6. React函数式组件和类组件[Dan]

    一篇对Dan的 How Are Function Components Different from Classes? 一文的个人阅读总结,内容来自于此.强烈推荐阅读 Dan Abramov.的博客. ...

  7. react项目中使用antd

    1.antd官网: https://ant.design/docs/react/introduce-cn 2.React中使用Antd 1.安装antd npm install antd --save ...

  8. react+dva 全局model中异步获取数据state在组件中取不到值

    先上结论,不是取不到,是写法有问题. 全文分4部分,1是问题描述,2是一开始的解决想法(错误做法),3是问题产生原因的思考,4是正常解决方法.只想看结论直接跳4 1.问题描述 接触react dva一 ...

  9. React函数式组件使用Ref

    目录: 简介 useRef forwardRef useImperativeHandle 回调Ref 简介 大家都知道React中的ref属性可以帮助我们获取子组件的实例或者Dom对象,进而对子组件进 ...

随机推荐

  1. 【Python爬虫】爬虫利器 requests 库小结

    requests库 Requests 是一个 Python 的 HTTP 客户端库. 支持许多 HTTP 特性,可以非常方便地进行网页请求.网页分析和处理网页资源,拥有许多强大的功能. 本文主要介绍 ...

  2. 当Hobject类型出现内存泄漏爆炸增长的问题,怎么处理

    尝试使用get,和set(在拍照之后,调用set,在obj使用前释放资源的思想来完成) HObject Get_inputImage() { return inputImage; } void Set ...

  3. js-小知识点

    强类型定义语言和弱类型定义语言1)强类型定义语言: 强制数据类型定义的语言.也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了.举个例子:如果你定义了一个整型 ...

  4. 【VUE】vue中遍历数组和对象

    一.遍历对象 对象数据 cities:{ "A":[{ "id": 56, "spell": "aba", " ...

  5. golang 获取当月最后一天日期

    now := time.Now() year, month, day := now.Date() //fmt.Println(year, month, day) //2021 September 1 ...

  6. linux 进程信号

    转载请注明来源:https://www.cnblogs.com/hookjc/ signal 函数的使用方法简单,但并不属于 POSIX 标准,在各类 UNIX 平台上的实现不尽相同,因此其用途受 到 ...

  7. 关于SVN常用命令之export

    SVN官方命令参考地址:http://www.subversion.org.cn/svnbook/nightly/svn.ref.html 关于export命令 导出一个干净的不带.svn文件夹的目录 ...

  8. Content-Type: multipart/form-data;文件上传利用

    当我们找到一个文件上传接口时,发现他的MIME类型检测为Content-Type: multipart/form-data;时,我们就可以尝试下面几种方法来绕过限制. ---------------- ...

  9. Java == 和 equals 的区别(面试描述)

    == == 是一个比较运算符 既可以判断基本类型,又可以判断引用类型 如果判断基本数据类型,判断的是值是否相等 如果判断的是引用类型,判断的是地址是否相等,判断是不是同一个对象 equals equa ...

  10. Solution -「NOI.AC 省选膜你赛」T2

      这道题就叫 T2 我有什么办法www 题目 题意简述   给定一个字符串 \(s\),其长度为 \(n\),求无序子串对 \((u,v)\) 的个数,其中 \((u,v)\) 满足 \(u,v\) ...