帮助
支持我们

从 React 切换到 Preact

preact/compat 是我们的兼容性层,它允许你利用 React 生态系统的众多库,并将其与 Preact 一起使用。如果你有现有的 React 应用程序,这是尝试 Preact 的推荐方法。

这让你可以继续编写 React/ReactDOM 代码,而无需更改你的工作流或代码库。preact/compat 会为你的包大小增加大约 2kb,但它有支持你可能在 npm 上找到的绝大多数现有 React 模块的优势。preact/compat 包在 Preact 核心之上提供了所有必要的调整,使其在单个模块中像 reactreact-dom 一样工作。



设置兼容性

要设置 preact/compat,你需要将 reactreact-dom 别名为 preact/compat入门页面详细介绍了如何在各种打包器中配置别名。

PureComponent

PureComponent 类与 Component 类似。不同之处在于,当新道具与旧道具相等时,PureComponent 将跳过渲染。为此,我们通过浅层比较旧道具和新道具,检查每个道具属性的引用相等性。通过避免不必要的重新渲染,这可以极大地加速应用程序。它通过添加一个默认的 shouldComponentUpdate 生命周期挂钩来工作。

import { render } from 'preact';
import { PureComponent } from 'preact/compat';

class Foo extends PureComponent {
  render(props) {
    console.log("render")
    return <div />
  }
}

const dom = document.getElementById('root');
render(<Foo value="3" />, dom);
// Logs: "render"

// Render a second time, doesn't log anything
render(<Foo value="3" />, dom);

请注意,PureComponent 的优势只有在渲染开销很大时才会显现。对于简单的子树,与比较道具的开销相比,直接进行 render 可能更快。

memo

memo 等效于函数组件,就像 PureComponent 等效于类。它在底层使用相同的比较函数,但允许你指定针对你的用例优化的自己的专门函数。

import { memo } from 'preact/compat';

function MyComponent(props) {
  return <div>Hello {props.name}</div>
}

// Usage with default comparison function
const Memoed = memo(MyComponent);

// Usage with custom comparison function
const Memoed2 = memo(MyComponent, (prevProps, nextProps) => {
  // Only re-render when `name' changes
  return prevProps.name === nextProps.name;
})

比较函数不同于 shouldComponentUpdate,因为它检查两个道具对象是否 相等,而 shouldComponentUpdate 检查它们是否不同。

forwardRef

在某些情况下,编写组件时,您希望允许用户获取树中更深层次的特定引用。使用 forwardRef,您可以“转发”ref 属性

import { createRef, render } from 'preact';
import { forwardRef } from 'preact/compat';

const MyComponent = forwardRef((props, ref) => {
  return <div ref={ref}>Hello world</div>;
})

// Usage: `ref` will hold the reference to the inner `div` instead of
// `MyComponent`
const ref = createRef();
render(<MyComponent ref={ref} />, dom)

此组件对库作者非常有用。

门户

在极少数情况下,您可能希望继续呈现到不同的 DOM 节点。目标 DOM 节点必须在尝试呈现到其中之前存在。

<html>
  <body>
    <!-- App is rendered here -->
    <div id="app"></div>
    <!-- Modals should be rendered here -->
    <div id="modals"></div>
  </body>
</html>
import { createPortal } from 'preact/compat';
import MyModal from './MyModal';

function App() {
  const container = document.getElementById('modals');
  return (
    <div>
      I'm app
      {createPortal(<MyModal />, container)}
    </div>
  )
}

请记住,由于 Preact 重用了浏览器的事件系统,因此事件不会通过门户容器冒泡到另一棵树。

Suspense(实验性)

Suspense 背后的主要思想是允许 UI 的部分显示某种占位符内容,而树中更深层次的组件仍在加载。一个常见的用例是代码拆分,在代码拆分中,您需要从网络加载组件才能呈现它。

import { Suspense, lazy } from 'preact/compat';

const SomeComponent = lazy(() => import('./SomeComponent'));

// Usage
<Suspense fallback={<div>loading...</div>}>
  <Foo>
    <SomeComponent />
  </Foo>
</Suspense>

在此示例中,UI 将显示 loading... 文本,直到加载 SomeComponent 并且 Promise 已解决。

此功能为实验性功能,可能包含错误。我们已将其作为早期预览包含在内,以提高测试可见性。我们不建议在生产中使用它。