找回密码
 立即注册

QQ登录

只需一步,快速开始

Richard.Ma 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
超级版主   /  发表于:2024-7-5 09:17  /   查看:585  /  回复:0
本帖最后由 Richard.Ma 于 2024-7-5 10:34 编辑

Wijmo 对 React 互操作性进行了重大改进,以支持函数式编程和 Next.js 支持。由于这些更新,一些客户可能会遇到重大更改(Breaking changes)。之前,我们已经将所有 React 示例迁移到函数式。我们继续在函数式 React 中完善 Wijmo,并宣布支持 Next.js!

为什么要做出这些改变?
我们对 React 互操作所做的所有这些更改都是为了改进 Wijmo 在 React 中的功能。这些更改的好处如下:
  • 功能组件:功能组件比类组件有几个优点,包括语法更简单、可读性更高、更容易理解组件行为。
  • 原生事件处理程序支持:功能组件无缝支持 React 样式的事件处理程序,无需使用其他钩子(如useEvent )即可添加事件。这简化了事件处理并减少了样板代码。
  • 增强的 TypeScript 支持:功能组件提供更好的 TypeScript 支持,便于类型检查并确保代码更健壮。这可以减少运行时错误并提高代码质量。

    • 对属性进行严格类型检查
    • 支持枚举类型属性中的字符串值

  • 与 Next.js 的兼容性:迁移到功能组件使 Wijmo 与 Next.js 兼容。
  • 改进了事件处理程序的闭包:函数式组件为事件处理程序提供了更好的闭包,与 React 的使用模式更加一致。这增强了代码的可维护性,并降低了与事件处理相关的意外行为的风险。


使用 strictStateMode() 管理 JSX 默认值和动态更新
已将strictStateMode选项添加到wijmo.react.base。默认情况下,此选项设置为false保持与现有用户应用程序的兼容性。如果用户希望按照 React 的状态管理理念使用 Wijmo API,他们可以将strictStateMode设置为true。因此,您需要选择加入此新行为。

使用strictStateMode(true)
  1. <font face="微软雅黑" size="3">import { strictStateMode } from "@mescious/wijmo.react.base";
  2. strictStateMode(true);</font>
复制代码

使用strictStateMode(true);将导致以下重大变化:
关键变化
  • JSX 中的默认值处理:依赖以前的行为在 JSX 中设置默认值的 React 应用程序在尝试直接使用 TypeScript 或 JavaScript 更新值时可能会遇到挑战。
  • FlexSheet 中的动态工作表添加:每个渲染周期中发生的控制状态更新会影响 FlexSheet 中动态工作表的添加,从而影响应用程序行为。
  • FlexGrid 中的列排序:JSX 同步会影响列排序,尤其是当列最初使用 JSX 定义时,这可能导致列布局出现意外行为。



重大变化Breaking changes
虽然这种重构带来了很多好处,但也可能会导致您的应用出现错误。下面,我们重点介绍了您可能遇到的问题及其解决方案。

如果依赖非自关闭的 JSX 组件,使用 React interop 的 TypeScript 项目可能会遇到与 JSX 语法相关的编译错误
React interop 现在是严格类型化的,因&#8203;&#8203;此根据构建设置,类型错误可能会阻止项目构建,直到所有错误都得到解决。
大多数情况下,类型错误很容易修复。我们只需要为属性分配正确的类型。
然而,一个错误也可能修复起来可能会更加复杂。
问题:TypeScript 编译错误“Children does not exist on type”

在上述错误中,TypeScript 编译器告诉我们无法将子项分配给 FlexChartLegend。
乍一看,似乎我们没有分配任何子元素。那么,为什么 TSC 会抛出错误?如果仔细观察,你会发现 FlexChartLegend 的开始和结束标记之间有一个空格,而 TSX 将该空格视为子元素,从而导致错误。

解决方案
为了修复这个问题,一定要使用自闭合的 TSX 标签来避免任何隐藏的子标签。
解决方案:使用自闭合 TSX 标签

用功能组件引用类型替换类组件类型(例如,将 FlexGrid 替换为 FlexGridRef)

在早期版本中,利用类组件允许直接将组件本身用作类型。但是,随着向函数式组件的过渡,这种方法不再可行。为了解决这个问题,我们为每个组件实现了引用类型。这些引用类型与控件同名,后缀为“Ref”。例如,如果控件名称为 FlexGrid,则其对应的引用类型为 FlexGridRef。
请注意以下代码片段中 gridRef ref 使用的类型:

2024 v1 hotfiex之前:
  1. import {FlexGrid} from "@mescius/wijmo.react.grid";
  2. import {useRef} from "react";
  3. function App(){
  4.   const gridRef = useRef<FlexGrid>();
  5.   const data = useState(getDummyData());
  6.   return (
  7.     <FlexGrid
  8.       ref = {gridRef}
  9.       itemsSource = {data}
  10.     />
  11.   );
  12. }
复制代码


2024 v1 hotfix:
  1. import {FlexGrid, FlexGridRef} from "@mescius/wijmo.react.grid";
  2. import {useRef} from "react";
  3. function App(){
  4.   const gridRef = useRef<FlexGridRef>();
  5.   const data = useState(getDummyData());
  6.   return (
  7.     <FlexGrid
  8.       ref = {gridRef}
  9.       itemsSource = {data}
  10.     />
  11.   );
  12. }
复制代码


依赖以前的行为在 JSX 中设置默认值的 React 应用可能会发现直接使用 TS/JS 代码更改值更加困难

注意:这仅适用于设置strictStateMode(true) 的情况;默认情况下,这不会对客户的应用程序造成重大改变。
在以前版本的 React interop 中,通过 JSX 提供给控件的值不会在每个渲染周期同步。只有当提供的值发生变化时,它们才会应用。这允许您首先通过 JSX 设置一个值,然后使用 JS/TS 代码更改其值,这是不正确的行为。
根据 React 设计,渲染状态应该始终反映提供的状态。
在最新版本中,这一点得到了改进。现在,通过 JSX/TSX 提供给组件的值始终与渲染的控件同步。如果通过 JSX 设置值,则无法在运行时更改该值而不更新状态。
运行时 React JSX 值渲染同步差异


在上面的例子中,我们为两个不同的属性分配了默认值:allowResizing 和 allowSorting。
乍一看,两者似乎相同,但有一个主要区别:allowResizing 直接被分配一个 false 值,而在 allowSorting 的情况下,使用状态变量。
这种差异使得我们可以在运行时改变 allowSorting 的值,而 allowResizing 的值在运行时无法改变并且始终保持为 false。

解决方案
  • 如果需要在运行时更改值,请使用状态变量来分配值
  • 不要通过 JSX 分配值,而是使用初始化事件并设置一次默认值,这样它们就不会在每个渲染周期同步
  • 要一次为多个控件设置默认值,我们还可以使用 useEffect 钩子,如下所示:



[React][TreeView][Accordion] 由于引入了包装 <div> 元素,TabPanel 和 Accordion 组件可能会出现布局不一致或意外样式的问题

React interop 用于 Tab 和 AccordionPane 组件,以前提供的 HTML 内容直接添加到控件主体中,现在则包裹在 div 元素内。
此更改可能会影响依赖于原始结构的 CSS 样式。为了减少干扰,添加到所提供 HTML 根目录的 CSS 类将复制到包装器元素,从而确保对现有样式实现的影响最小。
我们预计很少有应用程序会受到此变化的影响。
标签面板 HTML

以前的 DOM 结构

React 组件中更新的 DOM 结构

与之前的版本相比,更新后的 Tab 和 AccordionPane 组件的 React 互操作性和生成的 DOM 结构包括额外的 div 元素,包裹了标题和窗格主体。


0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部