本帖最后由 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): - <font face="微软雅黑" size="3">import { strictStateMode } from "@mescious/wijmo.react.base";
- strictStateMode(true);</font>
复制代码
使用strictStateMode(true);将导致以下重大变化: 关键变化- JSX 中的默认值处理:依赖以前的行为在 JSX 中设置默认值的 React 应用程序在尝试直接使用 TypeScript 或 JavaScript 更新值时可能会遇到挑战。
- FlexSheet 中的动态工作表添加:每个渲染周期中发生的控制状态更新会影响 FlexSheet 中动态工作表的添加,从而影响应用程序行为。
- FlexGrid 中的列排序:JSX 同步会影响列排序,尤其是当列最初使用 JSX 定义时,这可能导致列布局出现意外行为。
重大变化(Breaking changes)虽然这种重构带来了很多好处,但也可能会导致您的应用出现错误。下面,我们重点介绍了您可能遇到的问题及其解决方案。
如果依赖非自关闭的 JSX 组件,使用 React interop 的 TypeScript 项目可能会遇到与 JSX 语法相关的编译错误
React interop 现在是严格类型化的,因​​此根据构建设置,类型错误可能会阻止项目构建,直到所有错误都得到解决。 大多数情况下,类型错误很容易修复。我们只需要为属性分配正确的类型。 然而,一个错误也可能修复起来可能会更加复杂。 问题:TypeScript 编译错误“Children does not exist on type”
在上述错误中,TypeScript 编译器告诉我们无法将子项分配给 FlexChartLegend。 乍一看,似乎我们没有分配任何子元素。那么,为什么 TSC 会抛出错误?如果仔细观察,你会发现 FlexChartLegend 的开始和结束标记之间有一个空格,而 TSX 将该空格视为子元素,从而导致错误。
解决方案为了修复这个问题,一定要使用自闭合的 TSX 标签来避免任何隐藏的子标签。 解决方案:使用自闭合 TSX 标签
用功能组件引用类型替换类组件类型(例如,将 FlexGrid 替换为 FlexGridRef)
在早期版本中,利用类组件允许直接将组件本身用作类型。但是,随着向函数式组件的过渡,这种方法不再可行。为了解决这个问题,我们为每个组件实现了引用类型。这些引用类型与控件同名,后缀为“Ref”。例如,如果控件名称为 FlexGrid,则其对应的引用类型为 FlexGridRef。 请注意以下代码片段中 gridRef ref 使用的类型:
2024 v1 hotfiex之前: - import {FlexGrid} from "@mescius/wijmo.react.grid";
- import {useRef} from "react";
- function App(){
- const gridRef = useRef<FlexGrid>();
- const data = useState(getDummyData());
- return (
- <FlexGrid
- ref = {gridRef}
- itemsSource = {data}
- />
- );
- }
复制代码
2024 v1 hotfix: - import {FlexGrid, FlexGridRef} from "@mescius/wijmo.react.grid";
- import {useRef} from "react";
- function App(){
- const gridRef = useRef<FlexGridRef>();
- const data = useState(getDummyData());
- return (
- <FlexGrid
- ref = {gridRef}
- itemsSource = {data}
- />
- );
- }
复制代码
依赖以前的行为在 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 元素,包裹了标题和窗格主体。
|