从一个表格render方法问题看React函数组件的更新

最近在开发中碰到了一个现象觉得很有典型能作为例子所以给大家分享一下,从这个现象我们能很清楚的看到函数组件的更新的特点,以及我们应该如何去理解和拥抱函数组件。

问题的产生

需求

假设我们现在有两个表格,这里我们称之为A表和B表,这两个表的切换通过用户的点击触发,这里我们使用antd的table组件去实现这个表格。我们其实有两种思路,第一种就是我们动态切换表格的列配置和数据源,第二种是创建两个固定的表格,我们通过一个值来切换这两个的切换。这里我使用到是第一种方式。

实现

首先我们需要创建数组作为表格的两种column配置

const columns1 = [{title:'姓名',dataIndex:'name',key:"name"},{title:'性别',dataIndex:'sex',key:"sex"}]
const columns2 = [{...}...]
const data1 = [{id:1,name:'张珊',sex:"女"},{id:2,name:'李斯',sex:"男"},{id:3,name:'王五',sex:"男"}]
const data2 = [{...}...]

上面我举了很简单的两个例子,我们创建了两个列配置,那接下来我们需要一个state来判断当前需要使用的列配置,这里可以直接用state保存配置也可通过state来判断使用哪个配置。这里我们直接使用state保存列配置,那么table组件对应的使用应该如下所示:

const [currentColumns,setCurrentColumns ] = useState([])return (.<Table dataSource={dataSource} columns={currentColumns} />;.
)

然后我们使用的时候直接动态的setCurrentColumns就可以了,数据源的更改和列配置是一样的。

问题

本来上面的方法没有任何问题,但是假设A表的配置使用的是columns1,后端给你返回的性别字段并不是文字而是数字,这个时候你就需要通数据字典去对应的显示性别,当然我们可以规定1为性别男,2为性别女,但是这是很理想的状态。如果我们性别这一列还需要跨性别等一系列特殊现象,并且这个数据字典需要我们去请求接口获取,那么我能当然的想到应该如下去做

const [allSex,setAllSex]=useState({})
useEffect(()=>{request().then(res=>{setAllSex(res)})
},[])

我们可以请求好对应的数据然后使用state保存下来供后面表格渲染使用,所以我们列配置也需要适当的变化一下:

const columns1 = [{title:'姓名',dataIndex:'name',key:"name"},{title:'性别',dataIndex:'sex',key:"sex",ender: (_, record) => {return allSex[record.sex]}}
]

到这里就基本写完了,但是你在测试的时候会发现性别这一栏是空的,通过排查你会发现render函数其实拿到的allSex是一个空对象。

问题分析

首先我们可以通过控制看到我们网络请求是否已经完成并且是否有值,在得到确定的信息后我们可以排除是请求的问题。其次排查代码逻辑发现并没有问题,这个时候我就想到了一个前端人耳熟能详的词——闭包。

我们都知道函数组件的本质就是函数,每个函数都有其独立的作用域,当我们每次更新state的值的时候,其实就是相当于重新创建了一个state,所以这也是为什么我们只能在useEffect中拿到更新后的state值的原因。所以我们可以联想到,虽然请求已经完成state更新了,但是表格的column的render函数拿到的其实是一开始定义的初始值,当state更新后函数组件已经是一个全新的函数了,所以最开始的column是无法拿到更新后的state的值的,拿到的只能是定义state的初始值。

解决

解决的办法很简单,我们使用一个useEffect函数,他的依赖是allSex,然后我们在这个useEffect中去调用setCurrentColumns的方法。

useEffect(()=>{setCurrentColumns(columns1)
},[allSex])

当allSex被赋值时会触发这个影响函数,此时我们调用setCurrentColumns,配置项里的render函数拿到的就是最新的allSex也就是请求成功后的allSex,这个时候表格就能正常渲染了。

从一个表格render方法问题看React函数组件的更新相关推荐

  1. 在React的render方法中使用箭头函数

    在 React 组件中绑定点击事件通常的做法使用 class 属性. class Foo extends Component {handleClick = () => {console.log( ...

  2. react 函数组件父组件调用子组件方法

    react 函数组件父组件调用子组件方法 父组件利用ref对子组件做标记,通过调用子组件方法更改子组件状态,也可以调用子组件方法 首先在父组件中 ,使用useRef创建一个ref import Log ...

  3. react函数组件 更新自动展示和暴露方法给父组件

    react函数组件 子组件接收参数变化时form表单自动接收展示 在更新数据时,子函数组件接收如组件传递过来的参数进行解析并展示,初始值通过initialValue属性定义. initialValue ...

  4. onclick=两个函数_[译]React函数组件和类组件的差异

    [译]React函数组件和类组件的差异 原文: https://overreacted.io/how-are-function-components-different-from-classes/ 在 ...

  5. 深入学习React函数组件性能优化三剑客useMemo、useCallback、memo

    Hook使用规则 只能在函数的最外层调用Hook,不能在循环.条件判断或子函数中调用. 只能在React函数组件或自定义Hook中调用Hook,不可在其他JavaScript函数中使用. useMem ...

  6. react 函数组件暴露方法

    场景 部分时候希望在子组件中暴露方法给父组件,使用 Class 组件时配合 ref 很容易拿到子组件实例,并且可以执行子组件上的方法. 但是函数组件没有组件实例,就算使用 ref 转发,也只会把 re ...

  7. vue 渲染函数处理slot_面试官:Vue 和 React 对于组件的更新粒度有什么区别?

    前言 我们都知道 Vue 对于响应式属性的更新,只会精确更新依赖收集的当前组件,而不会递归的去更新子组件,这也是它性能强大的原因之一. 例子 举例来说 这样的一个组件: <div> {{ ...

  8. React函数组件和类组件的区别

    定义组件有两个要求: 组件名称必须以大写字母开头 组件的返回值只能有一个根元素 函数组件 函数组件接收一个单一的 props 对象并返回了一个React元素 类组件 class Welcome ext ...

  9. React 函数组件导出自定义方法的办法说明

    在进行React开发时,函数组件是比较方便的,由于函数组件没有this指针,因此如果想在父组件里调用函数型子组件的方法,就需要用到React.useImperativeHandle 这个帮助函数. 办 ...

最新文章

  1. linux运维如何月薪过万?(收藏自用)
  2. C++_复合、委托、继承
  3. 基因组表达分析:如何选择RNA-seq vs. 芯片
  4. 去掉 Android工程中让人很不爽的“黄色警告”
  5. Python入门学习笔记11(静态方法、类方法与属性方法)
  6. Android_内存泄露
  7. ruby array_在Ruby中使用Array.pop和Array.shift方法从Array中删除元素
  8. mysql json数组拆分表_MaxCompute将json数组拆分成多行
  9. Spring学习8-Spring事务管理(注解式声明事务管理)
  10. Android 和 iOS 各有千秋
  11. Chrome、Firefox 浏览器常用设置及操作
  12. 在Mac OS X Lion上安装Ruby On Rails
  13. 《C语言入门经典》读后感(一)
  14. c语言love字符怎么打,love字母特殊符号
  15. WarDrive:使用Backtrack 4中的Kismet进行嗅探并使用GE绘制地图的简明攻略
  16. 第五章、 Linux 常用网络指令
  17. Windows搭建基于EClipse的CppUTest单元测试环境
  18. uniApp图片加水印
  19. Windows CreateFont:创建自己的字体
  20. 赢在云端:VMware跨云架构,让“云”卷“云”舒自由可控!——访VMware公司大中华区高级技术总监李刚

热门文章

  1. python读取读取txt文件与写入txt文件
  2. Joint Pose and Expression Modeling for Facial Expression Recognition 论文翻译
  3. chrome去广告插件
  4. Python 修改python插件包的默认安装路径
  5. 图片按指定比例缩放并压缩至指定大小,解决保存图片文件体积过大bug。
  6. matlab输入数据作方程,用MATLAB函数编写并求解微分方程
  7. vim正则表达式(转)
  8. style name=Base.Widget.AppCompat.ActionButton parent=android:Widget.Material.Acti
  9. 笔记本CPU更换硅脂、液金散热对比测试
  10. netty+kotlin实现双人联机坦克大战