目前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. Arduino+ESP32 之 驱动GC9A01圆形LCD(二),移植LVGL,跑示例程序,显示自制图片

    在前文Arduino+ESP32 之 驱动GC9A01圆形LCD(一), 我们已经移植好了arduino GFX库, 该库的示例程序内,还有LVGL的示例程序哦. arduino环境下移植lvgl是很 ...

  2. Xml的一些基本概念(摘抄自w3school.com.cn)

    一个Xml的文档示例: 点击查看代码 <?xml version="1.0" encoding="ISO-8859-1"?> <note> ...

  3. 「NOI十联测」奥义商店

    「NOI十联测」奥义商店 若lzz想花费最少的钱,那么显然要选择数目较少的颜色. 先考虑暴力的写法. 每次向两边统计,每个物品要求被买的概率可以由上一个物品推出. now=1;//now 被买概率 M ...

  4. 「YNOI2016」自己的发明

    「YNOI2016」自己的发明 不换根 基本的莫队吧... 子树直接转到dfs序上. 其余部分可以见 「SNOI2017」一个简单的询问. 换根 根root,查询x,分3种: root不在x子树内,按 ...

  5. unicode家族

    定义 如果把各种文字编码形容为各地的方言,那么Unicode就是世界各国合作开发的一种语言. Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储. UTF ...

  6. Java与网页JSP文件编码的小总结

    感谢大佬: https://www.cnblogs.com/yangguoe/p/8467672.html(编码发展史) https://blog.csdn.net/seabiscuityj/arti ...

  7. Java中float、double、long类型变量赋值添加f、d、L尾缀问题

    展开1. 添加尾缀说明 我们知道Java在变量赋值的时候,其中float.double.long数据类型变量,需要在赋值直接量后面分别添加f或F.d或D.l或L尾缀来说明.  其中,long类型最好以 ...

  8. 各种字体.效果和名字对应图. --- by 王朋

    原帖地址:http://www.oschina.net/question/565065_76244

  9. Linux文件系统与日志分析的了解

    Linux文件系统与日志分析 1.inode和block概述 2.模拟inode耗尽实验 3.ext类型文件恢复 4.xfs类型文件恢复 5.日志文件 6.日志分析 1.文件:文件是存储在硬盘上的,硬 ...

  10. pytest(13)-多线程、多进程执行用例

    有些项目的测试用例较多,测试用例时需要分布式执行,缩短运行时间. pytest框架中提供可用于分布式执行测试用例的插件:pytest-parallel.pytest-xdist,接下来我们来学习这两个 ...