Skip to content

Commit ce9fc93

Browse files
committed
Merge develop into docs/astro-migration
Brings in two content-only commits that landed on develop after the last sync: - 0e047ee docs: fix SSR section framing in React integration guide (#1688) - 79f2f15 docs: rewrite Vue integration guide around markRaw pattern (#1689) Both touch files we migrated from `docs/guide/` to `docs/src/content/docs/guide/`. Git's rename detection auto-applied the develop-side edits to the new locations — no conflicts. GitHub had flagged the PR as CONFLICTING because its mergeability check hadn't recomputed since develop's last push; pushing this merge clears that flag.
2 parents 51f3cc0 + 79f2f15 commit ce9fc93

2 files changed

Lines changed: 36 additions & 54 deletions

File tree

docs/src/content/docs/guide/integration-with-react.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ The HyperFormula API is identical in a React app and in plain JavaScript. This g
77

88
Install with `npm install hyperformula`. For other options, see the [client-side installation](/docs/guide/client-side-installation) section.
99

10+
::: tip TypeScript
11+
All examples use TypeScript. Remove the type annotations to use plain JavaScript.
12+
:::
13+
1014
## Basic usage
1115

1216
Hold the HyperFormula instance in a `useRef` so it survives re-renders. Initialize it inside `useEffect` and release it in the cleanup function. Use `useState` to toggle between raw formulas and computed values.
@@ -70,15 +74,13 @@ export default function SpreadsheetComponent() {
7074
}
7175
```
7276

73-
If you use JavaScript instead of TypeScript, drop the type annotations — the rest of the pattern is unchanged.
74-
7577
## `React.StrictMode` double invocation
7678

7779
In development, React runs effects twice (mount → unmount → mount) to surface cleanup bugs. The pattern above is correct for StrictMode because `destroy()` runs before the re-mount creates a new instance, so no work leaks between the two lifecycles. Do not switch to a module-scoped singleton as a workaround — it will break StrictMode semantics.
7880

7981
## Server-side rendering (Next.js App Router)
8082

81-
The component above is already SSR-safe — the engine is constructed in `useEffect`, which never runs on the server. If you still want to skip the initial bundle on the server (it is a few hundred kB), wrap it in a client-only dynamic import.
83+
The component above is already SSR-safe — the engine is constructed in `useEffect`, which never runs on the server. If you still want to keep HyperFormula out of the initial JS bundle sent to the browser (it is a few hundred kB), wrap it in a client-only dynamic import.
8284

8385
In the App Router, `dynamic(..., { ssr: false })` is only allowed inside a client component. Put the dynamic call in a `'use client'` wrapper and import the wrapper from your server page:
8486

docs/src/content/docs/guide/integration-with-vue.md

Lines changed: 31 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,67 +7,47 @@ The HyperFormula API is identical in a Vue 3 app and in plain JavaScript. This g
77

88
Install with `npm install hyperformula`. For other options, see the [client-side installation](/docs/guide/client-side-installation) section.
99

10-
## Basic usage
11-
12-
Wrap the HyperFormula instance inside a plain class so it stays outside Vue's reactivity system (see [Troubleshooting](#vue-reactivity-issues) below for why this matters). Hold derived data in `ref` so the template updates when you reassign the ref's `.value`.
10+
::: tip TypeScript
11+
All examples use TypeScript. Remove the type annotations to use plain JavaScript.
12+
:::
1313

14-
```typescript
15-
// spreadsheet-provider.ts
16-
import { HyperFormula, type CellValue } from 'hyperformula';
17-
18-
export class SpreadsheetProvider {
19-
private hf: HyperFormula;
20-
21-
constructor(data: (string | number | null)[][]) {
22-
this.hf = HyperFormula.buildFromArray(data, {
23-
licenseKey: 'gpl-v3',
24-
// more configuration options go here
25-
});
26-
}
27-
28-
getCalculatedValues(): CellValue[][] {
29-
return this.hf.getSheetValues(0);
30-
}
31-
32-
getRawFormulas(): (string | number | null)[][] {
33-
return this.hf.getSheetSerialized(0) as (string | number | null)[][];
34-
}
35-
36-
destroy() {
37-
this.hf.destroy();
38-
}
39-
}
40-
```
14+
## Basic usage
4115

42-
Use the class from a component with `<script setup>`:
16+
Pass the HyperFormula instance through Vue's [`markRaw`](https://vuejs.org/api/reactivity-advanced.html#markraw) to opt it out of the reactivity system (see [Troubleshooting](#vue-reactivity-issues) below for why this matters). Hold derived data in `ref` so the template updates when you reassign the ref's `.value`.
4317

4418
```vue
4519
<script setup lang="ts">
46-
import { onUnmounted, ref } from 'vue';
47-
import type { CellValue } from 'hyperformula';
48-
import { SpreadsheetProvider } from './spreadsheet-provider';
49-
50-
const provider = new SpreadsheetProvider([
51-
[1, 2, '=A1+B1'],
52-
// your data rows go here
53-
]);
20+
import { markRaw, onUnmounted, ref } from "vue";
21+
import { HyperFormula, type CellValue } from "hyperformula";
22+
23+
const hf = markRaw(
24+
HyperFormula.buildFromArray(
25+
[
26+
[1, 2, "=A1+B1"],
27+
// your data rows go here
28+
],
29+
{ licenseKey: "gpl-v3" },
30+
),
31+
);
5432
5533
const values = ref<CellValue[][]>([]);
5634
5735
function runCalculations() {
58-
values.value = provider.getCalculatedValues();
36+
values.value = hf.getSheetValues(0);
5937
}
6038
6139
function reset() {
6240
values.value = [];
6341
}
6442
65-
onUnmounted(() => provider.destroy());
43+
onUnmounted(() => hf.destroy());
6644
</script>
6745
6846
<template>
69-
<button @click="runCalculations">Run calculations</button>
70-
<button @click="reset">Reset</button>
47+
<button @click="runCalculations" :disabled="!!values.length">
48+
Run calculations
49+
</button>
50+
<button @click="reset" :disabled="!values.length">Reset</button>
7151
<table v-if="values.length">
7252
<tr v-for="(row, r) in values" :key="r">
7353
<td v-for="(cell, c) in row" :key="c">{{ cell }}</td>
@@ -76,11 +56,11 @@ onUnmounted(() => provider.destroy());
7656
</template>
7757
```
7858

79-
The class keeps the HyperFormula instance as a private field, so Vue's reactivity Proxy never reaches it. This is the same pattern used in the [Vue 3 demo](#demo).
59+
`hf` is marked raw so Vue never proxies it — `values` is the only reactive piece. To mutate data, call any HyperFormula method (e.g. `setCellContents`) then reassign `values.value` to trigger a re-render. See [Basic operations](basic-operations.md) for the full mutation API.
8060

8161
## Server-side rendering (Nuxt)
8262

83-
The class above is already SSR-safe — HyperFormula has no browser-only API dependency. To skip the (otherwise wasted) server-side instantiation in Nuxt, wrap the component with `<ClientOnly>`.
63+
HyperFormula has no browser-only API dependency. To skip server-side computation, wrap the component with `<ClientOnly>`.
8464

8565
## Troubleshooting
8666

@@ -92,16 +72,16 @@ If you encounter an error like
9272
Uncaught TypeError: Cannot read properties of undefined (reading 'licenseKeyValidityState')
9373
```
9474

95-
it means that Vue's reactivity system tried to deeply observe the HyperFormula instance. Vue wraps reactive objects in a `Proxy` that intercepts every property access; when that proxy reaches a non-trivial instance with its own internal state, identity checks and lazy-initialized maps break. The fix is to opt the instance out of reactivity with Vue's [`markRaw`](https://vuejs.org/api/reactivity-advanced.html#markraw):
75+
it means that Vue's reactivity system tried to deeply observe the HyperFormula instance. Vue wraps reactive objects in a `Proxy` that intercepts every property access; when that proxy reaches a non-trivial instance with its own internal state, identity checks and lazy-initialized maps break. The fix is to opt the instance out of reactivity with [`markRaw`](https://vuejs.org/api/reactivity-advanced.html#markraw):
9676

9777
```typescript
98-
import { markRaw } from 'vue';
99-
import { HyperFormula } from 'hyperformula';
78+
import { markRaw } from "vue";
79+
import { HyperFormula } from "hyperformula";
10080

101-
const hfInstance = markRaw(
81+
const hf = markRaw(
10282
HyperFormula.buildEmpty({
103-
licenseKey: 'gpl-v3',
104-
})
83+
licenseKey: "gpl-v3",
84+
}),
10585
);
10686
```
10787

0 commit comments

Comments
 (0)