Closed telephant closed 1 week ago
The data on dom is correctly update, but solid components can't receive it.
And if I update roomId
the dom in devtools, the solid components will not update as well
We would greatly benefit from a reproduction for this. Something a little more tangible than import in a React project.
Hi, thanks for your reply.😊
I tried the vue project and offcial demo, encountering the same issue. It doesn't seem to be a 'React thing'.
I just update the demo project mentioned in official README.md document.
I added property to pass the room
argument to the web component.
The default value of room
is 'ccc', and the Stroybook passed argument value is 'eeee'. However the dom rendered the default value 'ccc' instead of 'eeee'. Even when I tried updating the room
property directly through devtools. It didn't have any effect.
Reproduce: https://studio.webcomponents.dev/edit/WPJFBXuhVhYMD4lEYtNr/src/index.stories.js?p=README.md
As far as I can tell the example works. The storybook version gets the updated eeee
and the Readme gets the default because a value isn't set there. Upon setting it in the Readme.md I see the updated value.
As far as I can tell the example works. The storybook version gets the updated
eeee
and the Readme gets the default because a value isn't set there. Upon setting it in the Readme.md I see the updated value.
Oh! Yes, you are right. I made a mistake of this online editor, it renders README.md
by default.
So it works for me now.
But in my project I still can not get the props
correctly.
Solid component:
import {
getCurrentElement,
} from 'solid-element';
import { customElement } from 'solid-element';
import {
onMount,
onCleanup,
createSignal,
type Component,
} from 'solid-js';
import { extractCss } from "solid-styled-components";
import tailwindStyles from '../../../assets/styles/tailwind.css?inline';
import varStyles from '../../../assets/styles/var.css?inline';
import LivePush from '../push';
const sheet = new CSSStyleSheet();
sheet.replaceSync(tailwindStyles);
interface LiveMainProps {
roomId: string;
type: 'push' | 'player';
}
const LiveMain: Component<LiveMainProps> = (props) => {
const {
roomId,
type,
} = props;
const [_roomId, setRoomId] = createSignal(roomId);
onMount(() => {
const ele = getCurrentElement();
if (ele.shadowRoot) {
ele.shadowRoot.adoptedStyleSheets = [sheet];
const cssText = extractCss();
const styleVar = document.createElement('style');
styleVar.textContent = varStyles;
ele.shadowRoot.appendChild(styleVar);
const style = document.createElement('style');
style.textContent = cssText;
ele.shadowRoot.appendChild(style);
}
// 初始设置 roomId
setRoomId(ele.getAttribute('roomId') || props.roomId);
// 创建一个 MutationObserver 来监听属性变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'roomId') {
const newRoomId = ele.getAttribute('roomId');
setRoomId(newRoomId || props.roomId);
console.log('RoomId updated:', newRoomId);
}
});
});
observer.observe(ele, { attributes: true });
// 清理函数
onCleanup(() => {
observer.disconnect();
});
});
return (
<div>
<p class="text-4xl text-red-600 test222">
{roomId}
</p>
<p class="text-4xl text-red-600 test222">
{_roomId()}
</p>
{type === 'push' && (
<LivePush
roomId={_roomId()}
/>
)}
</div>
);
};
customElement<{ roomId: string, type: 'push' | 'player' }>(
'cst-live',
{ roomId: '1', type: 'push' },
LiveMain,
);
vite.config:
import * as path from 'path';
import { fileURLToPath } from 'url';
import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts';
import solidPlugin from 'vite-plugin-solid';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const __packageDir = path.resolve(__dirname, '../');
export default defineConfig({
plugins: [
dts({
tsconfigPath: './tsconfig.json',
rollupTypes: true,
}),
solidPlugin(),
],
resolve: {
alias: {
'@cst-live-sdk': path.resolve(__packageDir, 'cst-live-sdk/src/index.ts'),
'@cst-request-encryption': path.resolve(__packageDir, 'cst-request-encryption/src/index.ts'),
'@cst-media-device': path.resolve(__packageDir, 'cst-media-device/src/index.ts'),
'@common-library': path.resolve(__packageDir, 'common-library/src/index.ts'),
'@cst-web-rtc-sdk': path.resolve(__packageDir, 'cst-web-rtc-sdk/src/index.ts'),
},
},
css: {
modules: {
localsConvention: 'dashesOnly',
},
},
build: {
outDir: 'dist',
target: 'esnext',
emptyOutDir: true,
lib: {
entry: path.resolve(__dirname, 'src/index.ts'),
name: 'CSTLiveSolutionSDK',
fileName: (format) => {
return `${format}/index.js`;
},
},
rollupOptions: {
external: [],
output: {
globals: {
// 'solid-js': 'SolidJS',
// 'solid-element': 'SolidElement',
},
},
},
},
});
package.json:
{
"name": "cst-live-solution-sdk",
"version": "0.0.1",
"description": "",
"main": "dist/index.js.mjs",
"types": "dist/index.d.ts",
"scripts": {
"start": "vite",
"dev": "vite build --watch --mode development",
"build": "vite build",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"autoprefixer": "^10.4.20",
"postcss": "^8.4.40",
"solid-devtools": "^0.29.2",
"tailwindcss": "^3.4.7",
"typescript": "5.4.2",
"vite": "^5.0.11",
"vite-plugin-solid": "^2.8.2"
},
"dependencies": {
...,
"solid-element": "^1.8.1",
"solid-js": "^1.8.11",
"solid-styled-components": "^0.28.5",
"tslib": "^2.5.0",
"typescript": "^5.4.0",
"video.js": "^8.17.4",
"vite-plugin-dts": "^4.1.0"
}
}
I can get properties correctly from const ele = getCurrentElement(); ele. getAttribute('roomId');
If I had to guess it is because you are destructuring props and losing reactivity. So while it may get the initial value it won't get any updated one.
Thank you for the suggestion, I tried to remove the props destructuring but it doesn't work. Here is the code:
import {
customElement,
getCurrentElement,
} from 'solid-element';
import {
onMount,
createSignal,
type Component,
} from 'solid-js';
import { extractCss } from "solid-styled-components";
import tailwindStyles from '../../../assets/styles/tailwind.css?inline';
import varStyles from '../../../assets/styles/var.css?inline';
import LivePush from '../push';
const sheet = new CSSStyleSheet();
sheet.replaceSync(tailwindStyles);
interface LiveMainProps {
roomId: string;
type: 'push' | 'player';
}
export const LiveMain: Component<LiveMainProps> = (props) => {
const [_roomId] = createSignal(props.roomId);
onMount(() => {
const ele = getCurrentElement();
if (ele.shadowRoot) {
ele.shadowRoot.adoptedStyleSheets = [sheet];
const cssText = extractCss();
const styleVar = document.createElement('style');
styleVar.textContent = varStyles;
ele.shadowRoot.appendChild(styleVar);
const style = document.createElement('style');
style.textContent = cssText;
ele.shadowRoot.appendChild(style);
}
});
return (
<div>
<p class="text-4xl text-red-600 test222">
{props.roomId}
</p>
<p class="text-4xl text-red-600 test222">
{_roomId()}
</p>
{props.type === 'push' && (
<LivePush
roomId={_roomId()}
/>
)}
</div>
);
};
const data: { roomId: string, type: 'push' | 'player' } = { roomId: 'test', type: 'push' };
customElement<{ roomId: string, type: 'push' | 'player' }>(
'cst-live',
data,
(props) => {
console.log('🚀 ===== props:', props); // still get default value: { roomId: 'test', type: 'push' }
return LiveMain(props);
},
);
Should I add some extra plugin for vite to support the web component in solidjs?
No only standard Solid plugin is needed. There is still a misunderstanding in the code. Solid only runs components once. Removing the signal altogether and using props.room
directly in the JSX should alleviate some of this. Also can't see inside LivePush but I'd be looking for similar issues.
As simple debug try console.log props.roomId
inside createEffect
OMG,I sorted it out. Web components can process the camel case which I used in my project. 🥺 😭
Thank you so much for your help!!!!!!!!!!! And this is my first SolidJs
project, it's awesome! Do you have any recommendations for headless components in solidJS or web components
Oh right.. let me see where it is documented. But it's possible there's some camel case dash case conversion going on. Sorry I wrote the core library here a decade ago and I don't use it often anymore so I'm a bit foggy.
Yeah.. if you set your props as camelCase it makes them as dash cased attributes by default. So roomId
would be room-id
as an attribute (but still roomId
as a property on the element).
You can override it with a prop definition that sets what you want the attribute name to be. I need to document this. But passing an object with value and attribute will do that:
customElement<{ roomId: string, type: 'push' | 'player' }>(
'cst-live',
{ roomId: {
value: '1',
attribute: "roomid" // force it to just be lowercase version
}, type: 'push' },
LiveMain,
);
Oh right.. let me see where it is documented. But it's possible there's some camel case dash case conversion going on. Sorry I wrote the core library here a decade ago and I don't use it often anymore so I'm a bit foggy.
Yeah.. if you set your props as camelCase it makes them as dash cased attributes by default. So
roomId
would beroom-id
as an attribute (but stillroomId
as a property on the element).You can override it with a prop definition that sets what you want the attribute name to be. I need to document this. But passing an object with value and attribute will do that:
customElement<{ roomId: string, type: 'push' | 'player' }>( 'cst-live', { roomId: { value: '1', attribute: "roomid" // force it to just be lowercase version }, type: 'push' }, LiveMain, );
Yesss!
Describe the bug
I've encountered an issue with
solid-element
where reactive properties are not updating correctly when the Props change.Your Example Website or App
none
Steps to Reproduce the Bug or Issue
solid-element
Expected behavior
Solid components can receive props correctly and reactively
Screenshots or Videos
LiveMain is a solid component, can not receive the
roomId
correctly.Below is the React project which import solid web componets