React
If you are looking for how to use React components as custom components, please refer to here.
Before integrating Univer into a React project, please ensure you have read the Univer installation and basic usage section and understand the basic concepts and lifecycle hooks of React.
Integrating Univer with React 18 & 19
Integration Steps
- Initialize Univer in the
useEffect
hook - Destroy Univer in the return function of the
useEffect
hook
Example
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'
import { useEffect, useRef } from 'react'
import '@univerjs/preset-sheets-core/lib/index.css'
export function App() {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const { univerAPI } = createUniver({
locale: LocaleType.EN_US,
locales: {
[LocaleType.EN_US]: mergeLocales(
UniverPresetSheetsCoreEnUS,
),
},
presets: [
UniverSheetsCorePreset({
container: containerRef.current,
}),
],
})
univerAPI.createWorkbook({})
return () => {
univerAPI.dispose()
}
}, [])
return (
<div ref={containerRef} />
)
}
Integrating Univer with React 16.9+ & 17
Notes before integration
Compatibility Notes
Univer's view layer is developed based on React 18.3.1, but we provide minimal compatibility support for React 16.9+ & 17 projects. Please note that this does not mean low versions of React will be supported indefinitely; we recommend upgrading to the latest version as soon as possible for the best experience and new features.
Build Tool Alias Configuration
In a React 16.9+ & 17 environment, you need to use the alias feature of your build tool to simulate the export of react-dom/client
, otherwise some features may not work properly.
Vite Configuration Example
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'react-dom/client': path.resolve(__dirname, './src/client.ts'),
},
},
})
import ReactDOM from 'react-dom'
export function createRoot(container: HTMLElement) {
return {
render: (element: JSX.Element) => {
ReactDOM.render(element, container)
},
}
}
CDN/UMD Scene Adaptation
If you are including Univer and React via <script>
tags, you also need to ensure that the following code is added after importing React to simulate the export of react-dom/client
:
<script>
/**
* With the support for React 19[^1], UMD users may need additional adaptation.
*
* [^1]: [support for React 19] https://github.com/dream-num/univer/pull/4247
*/
/**
* Fix `Uncaught TypeError: client.createRoot is not a function`
* If using UMD React < 18, you might need the following code.
*/
;(function (global) {
'use strict'
if (!global.ReactDOM) {
throw new Error('ReactDOM must be loaded before ReactCreateRoot.')
}
const ReactDOM = global.ReactDOM
if (!ReactDOM.createRoot) {
ReactDOM.createRoot = function (container) {
return {
render: (element) => {
ReactDOM.render(element, container)
},
}
}
}
})(this)
/**
* Fix `Uncaught TypeError: jsxRuntime.jsx is not a function`
* If using UMD React, you might need the following code.
* Reference: https://unpkg.com/react@18.3.1/cjs/react-jsx-runtime.production.min.js
*/
;(function (global) {
'use strict'
if (!global.React) {
throw new Error('React must be loaded before ReactJSXRuntime.')
}
const React = global.React
if (!React.jsx || !React.jsxs) {
const REACT_ELEMENT_TYPE = Symbol.for('react.element')
const hasOwnProperty = Object.prototype.hasOwnProperty
const RESERVED_PROPS = {
key: true,
ref: true,
__self: true,
__source: true,
}
const ReactCurrentOwner = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner
function createReactElement(type, config, maybeKey) {
const props = {}
let key = null
let ref = null
if (maybeKey !== undefined) {
key = `${maybeKey}`
}
if (config.key !== undefined) {
key = `${config.key}`
}
if (config.ref !== undefined) {
ref = config.ref
}
for (var propName in config) {
if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
props[propName] = config[propName]
}
}
if (type && type.defaultProps) {
const defaultProps = type.defaultProps
for (var propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName]
}
}
}
return {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
ref,
props,
_owner: ReactCurrentOwner.current,
}
}
React.jsx = createReactElement
React.jsxs = createReactElement
}
})(this)
</script>
Integration Steps
- Initialize Univer in the
useEffect
hook - Destroy Univer in the return function of the
useEffect
hook
Example
import { UniverSheetsCorePreset } from '@univerjs/preset-sheets-core'
import UniverPresetSheetsCoreEnUS from '@univerjs/preset-sheets-core/locales/en-US'
import { createUniver, LocaleType, mergeLocales } from '@univerjs/presets'
import { useEffect, useRef } from 'react'
import '@univerjs/preset-sheets-core/lib/index.css'
export function App() {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const { univerAPI } = createUniver({
locale: LocaleType.EN_US,
locales: {
[LocaleType.EN_US]: mergeLocales(
UniverPresetSheetsCoreEnUS,
),
},
presets: [
UniverSheetsCorePreset({
container: containerRef.current,
}),
],
})
univerAPI.createWorkbook({})
return () => {
univerAPI.dispose()
}
}, [])
return (
<div ref={containerRef} />
)
}
How is this guide?