Skip to content

Commit 006bc63

Browse files
authored
fix(🌎): reconciller bug on React Native Web (#3050)
1 parent f40bd9d commit 006bc63

File tree

5 files changed

+34
-26
lines changed

5 files changed

+34
-26
lines changed
Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Canvas, Rect } from "@shopify/react-native-skia/src";
2-
import { useEffect } from "react";
2+
import { useEffect, useState } from "react";
3+
import { Pressable } from "react-native";
34
import {
45
useSharedValue,
56
withRepeat,
@@ -8,6 +9,7 @@ import {
89
} from "react-native-reanimated";
910

1011
const AnimatedSquareCanvas = () => {
12+
const [rects, setRects] = useState(2);
1113
const x = useSharedValue(0);
1214
useEffect(() => {
1315
x.value = withRepeat(
@@ -18,11 +20,22 @@ const AnimatedSquareCanvas = () => {
1820
-1,
1921
);
2022
}, [x]);
21-
23+
console.log(rects);
2224
return (
23-
<Canvas style={{ width: "100%", height: "100%" }}>
24-
<Rect x={x} y={0} width={100} height={100} color="blue" />
25-
</Canvas>
25+
<Pressable onPress={() => setRects(i => i + 1)}>
26+
<Canvas style={{ width: "100%", height: "100%" }}>
27+
{Array.from({ length: rects }).map((_, i) => (
28+
<Rect
29+
key={i}
30+
x={x}
31+
y={i * 100}
32+
width={100}
33+
height={100}
34+
color="blue"
35+
/>
36+
))}
37+
</Canvas>
38+
</Pressable>
2639
);
2740
};
2841
export default AnimatedSquareCanvas;

‎external-apps/expo-router-app/yarn.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,7 @@ __metadata:
25492549

25502550
"@shopify/react-native-skia@file:../../packages/skia::locator=expo-router-app%40workspace%3A.":
25512551
version: 0.0.0
2552-
resolution: "@shopify/react-native-skia@file:../../packages/skia#../../packages/skia::hash=510f32&locator=expo-router-app%40workspace%3A."
2552+
resolution: "@shopify/react-native-skia@file:../../packages/skia#../../packages/skia::hash=931ba0&locator=expo-router-app%40workspace%3A."
25532553
dependencies:
25542554
canvaskit-wasm: 0.39.1
25552555
react-reconciler: 0.27.0
@@ -2563,8 +2563,8 @@ __metadata:
25632563
react-native-reanimated:
25642564
optional: true
25652565
bin:
2566-
setup-skia-web: ./scripts/setup-canvaskit.js
2567-
checksum: 79fae4837b5ee11fd1e0cd5eb0d480260a29308ef3396c1b7b0b057f79171ce0a055099b67a6a14ef925f806e1d63e8e047076cfe3a2f358ec3234377865f7fb
2566+
setup-skia-web: scripts/setup-canvaskit.js
2567+
checksum: 356c3002f9ef43820dea05a2976aec42e3aa916ebec7963d2522311714d500a0eb6a2c22727eb13fa1e1a892902ee1c6d4c370ab5027b3bf60bdb0e263148559
25682568
languageName: node
25692569
linkType: hard
25702570

‎packages/skia/src/sksg/Recorder/Core.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { SharedValue } from "react-native-reanimated";
2-
31
import type {
42
BlurMaskFilterProps,
53
CircleProps,
@@ -115,16 +113,16 @@ export type Command<T extends CommandType = CommandType> = {
115113
[key: string]: unknown;
116114
};
117115

118-
export const materializeProps = (command: {
119-
props: Record<string, unknown>;
120-
animatedProps?: Record<string, SharedValue<unknown>>;
121-
}) => {
116+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
117+
export const materializeCommand = (command: any) => {
122118
"worklet";
119+
const newProps = { ...command.props };
123120
if (command.animatedProps) {
124121
for (const key in command.animatedProps) {
125-
command.props[key] = command.animatedProps[key].value;
122+
newProps[key] = command.animatedProps[key].value;
126123
}
127124
}
125+
return { ...command, props: newProps };
128126
};
129127

130128
export const isCommand = <T extends CommandType>(

‎packages/skia/src/sksg/Recorder/Player.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,18 @@ import {
4444
isCommand,
4545
isDrawCommand,
4646
isGroup,
47-
materializeProps,
47+
materializeCommand,
4848
type Command,
4949
} from "./Core";
5050
import type { DrawingContext } from "./DrawingContext";
5151

52-
function play(ctx: DrawingContext, command: Command) {
52+
function play(ctx: DrawingContext, _command: Command) {
5353
"worklet";
54-
if (isGroup(command)) {
55-
command.children.forEach((child) => play(ctx, child));
54+
if (isGroup(_command)) {
55+
_command.children.forEach((child) => play(ctx, child));
5656
return;
5757
}
58-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59-
materializeProps(command as any);
58+
const command = materializeCommand(_command);
6059
if (isCommand(command, CommandType.SaveBackdropFilter)) {
6160
ctx.saveBackdropFilter();
6261
} else if (isCommand(command, CommandType.SaveLayer)) {

‎packages/skia/src/sksg/Recorder/commands/Box.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { deflate, inflate, processColor } from "../../../dom/nodes";
22
import type { BoxProps, BoxShadowProps } from "../../../dom/types";
33
import { BlurStyle, ClipOp, isRRect } from "../../../skia/types";
44
import type { Command } from "../Core";
5-
import { CommandType, materializeProps } from "../Core";
5+
import { CommandType, materializeCommand } from "../Core";
66
import type { DrawingContext } from "../DrawingContext";
77

88
interface BoxCommand extends Command<CommandType.DrawBox> {
@@ -17,11 +17,9 @@ export const isBoxCommand = (command: Command): command is BoxCommand => {
1717

1818
export const drawBox = (ctx: DrawingContext, command: BoxCommand) => {
1919
"worklet";
20-
command.shadows.forEach((shadow) => {
21-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22-
materializeProps(shadow as any);
20+
const shadows = command.shadows.map((shadow) => {
21+
return materializeCommand(shadow).props;
2322
});
24-
const shadows = command.shadows.map((shadow) => shadow.props);
2523
const { paint, Skia, canvas } = ctx;
2624
const { box: defaultBox } = command.props;
2725
const opacity = paint.getAlphaf();

0 commit comments

Comments
 (0)