一、问题描述

广告配置中绑定第三方规格ID表格数据,有一部分展示错乱,具体如下:

表格组件使用 Facebook 的 (fixed-data-table) 组件

二、原因分析

1.检查props

先查看下传入组件中的props是否正确,结果如下图:

发现传入EditableCell组件的data数据是没有问题的(和后台数据一致),但为什么渲染到页面中就不对呢?

2.单元格中的值currentValue出错

这样就直接将错误范围缩小到EditableCell组件,该组件渲染时出错,通过查看该组件源码,发现单元格中的值来自一个内部state: this.state.currentValue,该值在组件初始化时(constructor)设置了一次,在componentWillReceiveProps事件中也设置了一次,具体代码如下:

  constructor(props) {
super(props);
console.log('props:', props);
this.state = { editable: false, errorTips: '', currentValue: this.formatValue(props) };
}
  componentWillReceiveProps(nextProps) {
if(this.props.data !== nextProps.data) {
this.setState({currentValue: this.formatValue(nextProps)});
}
}

发现currentValue的值都被设置为:this.formatValue(props)

由于其值直接从render中取this.state.currentValue,于是将其打印出来,发现是错的;

再将this.formatValue(this.props)打印出来,值是对的:

3.原来是componentWillReceiveProps没执行

前面已经分析过,this.state.currentValue只在两个地方设置了值,于是在这两个地方分别打印下currentValue的值,结果是:

  • constructor执行了21次,打印了前21条数据的currentValue
  • componentWillReceiveProps 中设置currentValue的语句没有执行

当鼠标滚动到第22条数据的位置时,componentWillReceiveProps事件执行了,但是设置currentValue的语句没执行,因为 if(this.props.data !== nextProps.data)返回false,试着将判断条件去掉,发现一切正常。

三、解决方案

将componentWillReceiveProps事件中的 if(this.props.data !== nextProps.data)判断条件去掉

四、深入思考

问题是解决了,可还是总觉得有些地方不是很清楚,比如:

  • 为什么明明有25条数据,constructor却只执行了21次?
  • 为什么当鼠标滚动到第22条数据的位置时,componentWillReceiveProps事件会执行?

于是继续深入研究:

1.fixed-data-table数据渲染原理

通过观察react组件层次结构,发现只有21行数据:

另外4条数据哪去了?于是鼠标往下滚,滚到最后,发现DOM中还是只有21行数据,不过发现一个有趣的现象,最后一个DOM节点指向的并不是最后一条数据,而是第21条数据:

其他数据去哪儿了?

通过使用React元素检查器发现,最后4个数据居然跑到最前面去了:

于是猜想:

fixed-data-table并不是一次性将所有数据渲染到页面上,而是只渲染其中一部分(这里是21条数据),随着鼠标滚动动态渲染。

可是为什么是21行数据(21个DOM节点 FixedDataTableRow)?

2.源码研究:DOM节点数量的计算

通过研究fixed-data-table的源码FixedDataTableRowBuffer.js发现:

21这个数字的计算公式如下:

var MIN_BUFFER_ROWS = 3;
var MAX_BUFFER_ROWS = 6;
this._maxVisibleRowCount = Math.ceil(viewportHeight / defaultRowHeight) + 1;//ceil(437/48) = 11
this._bufferRowsCount = clamp(Math.floor(this._maxVisibleRowCount / 2), MIN_BUFFER_ROWS, MAX_BUFFER_ROWS);//clamp方法用于将value限制在[min, max]区间内,这里是[3, 6]
//floor(11/2)=5 clamp(5, 3, 6)=5 //关键代码
var viewportRowsCount = lastViewportRowIndex - firstViewportRowIndex + 1;//可视区域行数
var allowedRowsCount = viewportRowsCount + this._bufferRowsCount * 2;//DOM节点数量
// allowedRowsCount = 11 + 5*2 = 21

五、经验沉淀

  • 1.保持谨慎,并及时响应。不忽视小问题,因为小问题有可能会引发更大的问题,对问题及时响应和解决
  • 2.开发过程中,善于发现隐患,并及时解决
  • 3.充分自测,自己负责的项目要随时检查是否出故障,最好是能写单元测试,保证质量
  • 4.多向别人学习,了解不同的思维方式,提高自身解决问题的能力
  • 5.多总结反思,从问题和错误中学习

六、致谢&参考资料

结论

一句话总结:

表格单元格中的数据来源于一个内部state currentValue, 该值只在组件首次渲染时设置了一次,并且只设置了前21条数据的值(FixedDataTable动态数据加载机制的原因),而业务中由于一个if逻辑的错误,导致滚动鼠标时,剩余4条本应设置的currentValue没有被设置,从而组件使用了21条数据中的前4条数据的值,导致数据展示错误。

[BUGCASE]FixedDataTable表格数据渲染错误的更多相关文章

  1. 【日常笔记】datatables表格数据渲染

    现在有很多表格渲染方式 这里只是记录怎么使用datatables渲染数据 使用datatables可以更方便的来渲染数据 [中文api]http://datatables.club/index.htm ...

  2. layui表格数据渲染SpringBoot+Thymeleaf返回的数据时报错(Caused by: org.attoparser.ParseException: Could not parse as expression: ")

    layui table渲染数据时报错(Caused by: org.attoparser.ParseException: Could not parse as expression: ") ...

  3. vuejs的v-for遇到过的数据渲染错误的bug,原因是和key值有关

      <div v-for="(item,i) in doc" :key="i"> <el-row> <el-col :span=& ...

  4. Angular将填入表单的数据渲染到表格

    一.项目简介 我们将采用Angular框架来做一个demo,这个demo将要实现的功能如下: 在X坐标和Y坐标文本框输入信息,然后点击添加,就会在下面表格 中出现一项相应的数据,点击每一项旁边的删除按 ...

  5. 超全table功能Datatables使用的填坑之旅--1: 无法渲染表格数据: ajax调用了参数 : success

    问题:Datatables: 无法渲染表格数据 原因:datatables的ajax 传了"success":function(){},导致无法渲染数据. ajax 删掉" ...

  6. Vue电商后台管理系统项目第2天-首页添加表格动态渲染数据&分页

    0x01.使用Github学习的姿势 基于昨天的内容,今天的内容需要添加几个单文件组件,路由文件也需要做相应的增加,今天重点记录使用Element-UI中的表格组件实现数据动态渲染的实现流程和分页功能 ...

  7. Java读取Execl表格数据

    在前面提到用java代码新建一个Execl 表格并添加数据到表格中, 这次写了一个读取Execl表格数据并添加导数据库中的案列 给定对方一个Execl模板表格,如果导入的Execl表格和预订的表格不相 ...

  8. easyUI datagrid 多行多列数据渲染异常缓慢原因以及解决方法

    原因 最近,在优化之前公司帮联想(外包)做的一个老的后台管理系统,由于项目是基于easy UI框架,页面是后台用jsp实现的,再加上在公司推行前后端分离的实践,大部分项目都基于vue采用前后端分离去实 ...

  9. JAVA Freemarker + Word 模板 生成 Word 文档 (普通的变量替换,数据的循环,表格数据的循环,以及图片的东替换)

    1,最近有个需求,动态生成 Word 文当并供前端下载,网上找了一下,发现基本都是用 word 生成 xml 然后用模板替换变量的方式 1.1,这种方式虽然可行,但是生成的 xml 是在是太乱了,整理 ...

随机推荐

  1. 定位流之z-index属性

    1.固定定位是脱离标准流的,不会占用标准流的空间 2.和绝对定位有点像,也不区分行内块级元素 3.类似于前面学的背景关联方式(让某个背景图片不随滚动而滚动)让某个元素不随着滚动条的滚动而滚动 ie6不 ...

  2. [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法)

    [POJ 2821]TN's Kindom III(任意长度循环卷积的Bluestein算法) 题面 给出两个长度为\(n\)的序列\(B,C\),已知\(A\)和\(B\)的循环卷积为\(C\),求 ...

  3. 【Kata Daily 190929】Password Hashes(密码哈希)

    题目: When you sign up for an account somewhere, some websites do not actually store your password in ...

  4. Java自动化测试框架-02 - TestNG之理论到实践

    TestNG,即Testing, NextGeneration,下一代测试技术,是一套根据JUnit 和NUnit思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做集 ...

  5. 多服务器使用Docker设置一主一从三哨兵redis(完整)

    本来应该续之前那篇博客Docker配置redis哨兵模式--多服务器·上写一个下篇的,但是忽然意识到应该将必要的环境打包为一个基础镜像,在此基础上建立与redis有关的镜像,这样既能够快速打包,又能够 ...

  6. mac os 10.15安装jdk 1.6

    1.如果出现报错 已经安装了最高版本 下载请看:https://www.jianshu.com/p/3b580c405c7c 请看下面方法处理错误 1.在mac的访达中 找到 "脚本编辑器& ...

  7. Python图书管理系统

    图书管理系统 功能简介 添加图书时,图书ID不能重复,图书名可重复 删除,查询,修改功能,输入图书名之后提供所有的同名的图书,用户可以按照图书序号对具体的一本书进行操作 显示书籍,分行显示,每行一本书 ...

  8. ElementUI表格行编辑单元格编辑支持(输入框,选择框)Demo

    嗯,需要做成这个样子,所以网上查了些资料.整理了下.提供几个一个思路.不足之处请小伙伴指出来.  普通版的table可编辑内嵌select选择框,输出框,编辑删除添加等 <!DOCTYPE ht ...

  9. Redis 数据结构之字符串的那些骚操作

    Redis 字符串底层用的是 sds 结构,该结构同 c 语言的字符串相比,其优点是可以节省内存分配的次数,还可以... 这样写是不是读起来很无聊?这些都是别人咀嚼过后,经过一轮两轮三轮的再次咀嚼,吐 ...

  10. mdp文件-Chapter1-MINIM.mdp

    mdp文件是能量最小化,NVT模拟,NPT模拟与MD模拟的必须文件. mdp文件的详细解释可以参考官方文档http://manual.gromacs.org/online/mdp_opt.html 接 ...