oneiro
oneiro
SSolidJS
Created by oneiro on 11/10/2023 in #support
Set headers inside createServerAction$()
Hey folks, I am currently trying to explicitely set my content type header to Content-Type: application/json; charset=utf-8 because of some encoding issues. However I don't quite understand how I can do so inside a call of createServerAction$(). I tried to access responseHeaders from useRequest(), however they seem to be always undefined:
const [chartData, submitChartOptions] = createServerAction$(
async (opts: { type: ChartType; options: SubmitChartOptions }) => {
const { responseHeaders } = useRequest();

const result = await generateChartDataByType(opts);

responseHeaders.set("Content-Type", "application/json; charset=utf-8");

return result;
}
);
const [chartData, submitChartOptions] = createServerAction$(
async (opts: { type: ChartType; options: SubmitChartOptions }) => {
const { responseHeaders } = useRequest();

const result = await generateChartDataByType(opts);

responseHeaders.set("Content-Type", "application/json; charset=utf-8");

return result;
}
);
Any idea, what I am doing wrong here? Thanks in advance
3 replies
SSolidJS
Created by oneiro on 9/18/2023 in #support
Best way to dynamically access i18n-translations with typescript
Hey folks, I am currently using @solid-primitives/i18n (https://github.com/solidjs-community/solid-primitives/tree/main/packages/i18n#readme) for translation purposes. However there's one thing i struggle with: Some of the keys I would like to access are coming from an api, where each key is typed as generic string. For example imagine that my dict looks like this:
const en_dict = {
foo: {
bar: 'Bar',
baz: 'Baz'
}
}
const en_dict = {
foo: {
bar: 'Bar',
baz: 'Baz'
}
}
And I want to translate like this:
const translated = t(`foo.${apiResponse.key}`) // key could be any string here
const translated = t(`foo.${apiResponse.key}`) // key could be any string here
This of course makes typescript complain, as we can't be sure here that our key does actually exist inside the dict. What would be the best way to go about this here? I imagine I would need some form of wrapper around t() that still retains its api, but e.g. returns an empty string or throws an error if the key is not part of the dict. Are there any best practices how to deal with that? Thanks in advance 🙂
1 replies
SSolidJS
Created by oneiro on 9/18/2023 in #support
i18n and context issues
Hey folks, I am currently migrating to the 2.0.0 release of @solid-primitives/i18n. (https://github.com/solidjs-community/solid-primitives/tree/main/packages/i18n#readme) However I have a few questions: 1. The way t is being defined in the docs will always give me the famous reactive variable 'xxx' should be used within JSX error. Which makes sense. Therefore I wonder, why all examples are build this way even though locales and therefore the current dict might change? Is this an error on the library end or do I misunderstand something here? Here's what my Provider looks like:
export function I18nProvider(props: { children: JSXElement }) {
const [locale, setLocale] = createSignal<Locale>("en");
const dict = createMemo(() => i18n.flatten(dictionaries[locale()]));
const t = i18n.translator(dict);

return (
<I18nContext.Provider
value={{
t,
setLocale,
locale,
}}
>
{props.children}
</I18nContext.Provider>
);
}
export function I18nProvider(props: { children: JSXElement }) {
const [locale, setLocale] = createSignal<Locale>("en");
const dict = createMemo(() => i18n.flatten(dictionaries[locale()]));
const t = i18n.translator(dict);

return (
<I18nContext.Provider
value={{
t,
setLocale,
locale,
}}
>
{props.children}
</I18nContext.Provider>
);
}
2. Is there a way to make properties of a context provider still be reactive but not accessors? I find it a bit annyoing, that I need to use t()() instead of t() when consuming my context Thanks in advance 🙂
3 replies
SSolidJS
Created by oneiro on 8/17/2023 in #support
What's the best way to debug `Buffer is not defined`
Hey folks, I am currently trying to re-restructure my code a bit, so it becomes more maintainable. One thing I noticed, is that I sometimes receive a Buffer is not defined runtime error inside the browser when moving things. This happened for example, when I accidentally put a module inside one of my routes sub-directories which wasn't a module and just contained some stuff to be consumed. However I also seem to get the issue, when I export server-specific functions in various places. Generally there seem to be various sources leading to this error. Is there a good way to debug this and to make finding the cause of the issue easier than carefully reading my code and using trial and error? Thanks in advance!
3 replies
SSolidJS
Created by oneiro on 8/13/2023 in #support
What is the proper way to start solid-start in production (especially with something like pm2)?
Hey folks, I am currently running solid-start in production with a docker compose setup. Solid start is being run by first producing a build with running solid-start build and then invoking solid-start start. Is this the proper way to run solid-start in production? Is there a way to just run the output from solid-start build? When running something with pm2 for example you typically provide a single javascript file as scriptentrypoint. How would I do that with solid-start? I want to start clustering my application. But before I use something large like kubernetes for scaling, I want to use pm2 inside my docker-container. Thanks in advance 🙂
7 replies
SSolidJS
Created by oneiro on 8/3/2023 in #support
Best way to upload files from a form with solid-start?
Hey folks, I was wondering what the best way to upload a file with solid-start would be? Is there an easy way to use createServerAction$ or should I expose an API-route? (I couldn't really find any fully fledged examples, so if you know any, I would be very happy if you'd share them with me 🙂 ) Thanks in advance!
8 replies
SSolidJS
Created by oneiro on 7/28/2023 in #support
Easiest way to spin up an e2e/integration-test setup with solid-start?
Hey folks, I am currently trying to figure out what would be a good way to build an integration and e2e-testing setup for solid-start. Essentially my integration tests should be able to connect to a database and only test server-side logic (for UI stuff I would simply use testing-library). E2E-tests should spin up a database as well as the solid-start application. Now here are the hurdles I have yet to overcome: 1. I would definitely like to use docker to spin up my database (we use docker-compose for our dev setup anyway). Ideally in conjunction with test containers. However our database connection is currently initalized via environment variables from an .env-file and with testcontainers I am unsure how I would ideally overwrite these after our database has been imported (this would be necessary, as testcontainers use a random port and I would also need to get the host) 2. What would be the best/easiest way to start my server. Ofcourse I could also run my solid-start app inside another container, but that feels a bit more exessive than I would like. Ideally I could start the server without the need for a container from my tests. So my general question would probably be: what do your integration/e2e-testsetups generally look like, when working with solid-start? Thanks in advance 🙂
2 replies
SSolidJS
Created by oneiro on 7/25/2023 in #support
Suspense not updating when navigating to Route directly
Hey folks, I am currently having a weird issue I can't quite solve: We have a route which receives data via routeData + createServerData$. The routes JSX is wrapped with <Suspense />. Now when I navigate to this route from another route, our data will be set correctly and <Suspense /> will eventually resolve. However when I simply type the url in to my browser and navigate directly to the route, suspense will never resolve. data() keeps being undefined. I logged inside createServerData and the data seems to be correctly accumulated on the server, I just does not seem to be served to the client. Anything obvious I am missing here? Thanks in advance PS: I will try to create a minimal reproducable example asap - I just wanted to get this question ouf beforehand in case there's something obvious I am doing wrong 🙂
3 replies
SSolidJS
Created by oneiro on 7/15/2023 in #support
solid-transition-group leads to reactivity warning inside test cases
Hey folks, we just started using solid-transition-group and as soon as the <Transition />-component is present, all of our test cases start throwing the computations created outside a createRoot or render will never be disposed- error. If we remove the transition the error disappears. Any idea what could cause this? The component in question looks like this:
const Snackbar = () => {
return (
<Transition
onEnter={(element, done) => {
const animation = element.animate(
[
{ transform: "translate(-50%, -100%)" },
{ transform: "translate(-50%, 0%)" },
],
{
duration: 400,
}
);
animation.finished.then(done);
}}
onExit={(element, done) => {
const animation = element.animate(
[
{ transform: "translate(-50%, 0%)" },
{ transform: "translate(-50%, -100%)" },
],
{
duration: 400,
}
);
animation.finished.then(done);
}}
>
<Show when={toastSelectors.firstToast()}>
{(firstToast) => (
<Toast
id={firstToast().id}
kind={firstToast().kind}
message={firstToast().message}
/>
)}
</Show>
</Transition>
);
};
const Snackbar = () => {
return (
<Transition
onEnter={(element, done) => {
const animation = element.animate(
[
{ transform: "translate(-50%, -100%)" },
{ transform: "translate(-50%, 0%)" },
],
{
duration: 400,
}
);
animation.finished.then(done);
}}
onExit={(element, done) => {
const animation = element.animate(
[
{ transform: "translate(-50%, 0%)" },
{ transform: "translate(-50%, -100%)" },
],
{
duration: 400,
}
);
animation.finished.then(done);
}}
>
<Show when={toastSelectors.firstToast()}>
{(firstToast) => (
<Toast
id={firstToast().id}
kind={firstToast().kind}
message={firstToast().message}
/>
)}
</Show>
</Transition>
);
};
Thanks in advance
6 replies
SSolidJS
Created by oneiro on 7/13/2023 in #support
Issue with event delegation and a native library
Hey folks, I am currently trying to integrate a command palette library into our app. I tried various libraries and eventually ended up with solid-ninja-keys/ninja-keys. However there is one issue: solid-ninja-keys seems to be just a small wrapper around ninja-keys, ninjakeys itself seems to reliy on regular input events (e.g. keydown). Now when I have something with a keydown handler in my app (in my case it's a select field from solid-select) ninja-keys will no longer work (you can press cmd + k and the overlay appears, but all other shortcuts won't work). I have recreated the issue here: https://stackblitz.com/edit/solidjs-templates-dz5buc?file=src%2FApp.tsx So now I am wondering two things: 1. is there an easy way to fix this? 2. How hard is it in general to integrate regular js libraries into solid - is it as "hard" as in react or as "easy" as with svelte (I've only used react for many years and jumped to solid instead of svelte, but heard that svelte is pretty strong in that regard) Thanks in advance
25 replies
SSolidJS
Created by oneiro on 7/8/2023 in #support
Testing portals
Hey, I am currently trying to test a datepicker created with https://github.com/rnwonder/solid-date-picker with testing-libary. However I am not quite sure how to select the actual picker. It seems to get rendered into a div with the id portal-island, which also shows up in my test, but without its contents. What would be the general way to test this? I also tried to jsut use querySelector but am not sure, how to get the correct container element to attach the querySelector to. Thanks in advance
16 replies
SSolidJS
Created by oneiro on 7/4/2023 in #support
Is the createUniqueId-helper safe to use?
We are currently using the createUniqueId-helper on the client only and today one of our data entries was overwritten. We are relatively sure, that this was because its ID was generated a second time when we created a new data entry. Can id clashes happen? Ids are rather short, so I imagine that this is definitely a possibility. Would it be better to switch to something like nanoid here, which can be configured to use a longer id?
4 replies
SSolidJS
Created by oneiro on 7/3/2023 in #support
Are global signals ever reset between test runs?
@lexlohr Sorry - another issue 😅 As I've described in another issue I have structured my application in a way, that my global state mainly consists of global stores. Now to create tests I usually need to first populate my stores with some test data. This does seem to work fine in general, howerver I noticed, that apparently these stores will keep their state between tests. Is this a mistake on my end, am I using stores wrong, or is this a bug?
21 replies
SSolidJS
Created by oneiro on 7/3/2023 in #support
Access native html dialogs show/close methods in clickHandler
Hey folks, I am currently using native html dialogs inside my app and am accessing their show/close methods by using them from window (e.g. window.myModal.show()). However this is pretty error prone and also doesn't play well with testing. Is there a recommended way on how to use these without accessing the window? I thought of using refs but apparently these refs are not set, when my handler functions are created, so they stay undefined. 🤔 Ideally I would export show/close functions from my component file that could be used everywhere througout the app. Any idea what would be a good way to solve this?
15 replies
SSolidJS
Created by oneiro on 7/2/2023 in #support
Is there a way to debug how callbacks are called, when firing an event with testing-library?[SOLVED]
Hey, I am having a hard time testing my code and would like to find out if and how some of my event handlers are actually being called, when I run fireEvent.click() on a button. Some background: I am running solid inside a Tauri-Application which works very well. However my issue is, that on the click of a button nothing observable seems to happen (it works perfectly fine in the real running application). Basically what I am trying to do, is to setup some stores, render my app, find a button that should start a timer, advance these timers by using vitests fake timers and afterwards inspect, that a stop button is being rendered and the time has been adjusted accordingly. My current (simplified without timers) test looks like this:
it('should run on toggle start', async () => {
// Arrange
render(() => <App />, { location: '/' })
const TEST_ID = 'TEST_ENTRY'
setTimeEntries(TEST_ID, {
id: TEST_ID,
savedTimeInMs: 0,
date: '2023-07-02T00:00:00.000Z',
description: 'This is a test entry',
isBillable: true,
isFavorite: false,
})
setRunningTimer({
timeEntryId: TEST_ID,
savedTimeInMs: 0,
isRunning: false,
})
setIsHydrating(false)

// Act
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })

mockIPC(() => {
fireEvent.click(currentTimerStartButton)
})

// Assert
expect(await screen.findByRole('button', { name: 'stop-current-timer' })).toBeInTheDocument()
expect(await screen.findByTestId('running-timer-time')).toHaveTextContent('00:00:03')
})
it('should run on toggle start', async () => {
// Arrange
render(() => <App />, { location: '/' })
const TEST_ID = 'TEST_ENTRY'
setTimeEntries(TEST_ID, {
id: TEST_ID,
savedTimeInMs: 0,
date: '2023-07-02T00:00:00.000Z',
description: 'This is a test entry',
isBillable: true,
isFavorite: false,
})
setRunningTimer({
timeEntryId: TEST_ID,
savedTimeInMs: 0,
isRunning: false,
})
setIsHydrating(false)

// Act
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })

mockIPC(() => {
fireEvent.click(currentTimerStartButton)
})

// Assert
expect(await screen.findByRole('button', { name: 'stop-current-timer' })).toBeInTheDocument()
expect(await screen.findByTestId('running-timer-time')).toHaveTextContent('00:00:03')
})

(continuation in thread)
9 replies
SSolidJS
Created by oneiro on 7/1/2023 in #support
solidjs/testing-library using `location` but still getting <Router /> error
Hey, I am currently trying to setup on of my solid-apps with solidjs/testing-library. I want to test something on my main route, and am therefore using the location option. However my test still throws the Make sure your app is wrapped in a <Router />-error. Any idea what I could be doing wrong? Here's my test wip test case:
it('should run on toggle start', async () => {
// Arrange
// TODO:
// fill store with a time entry
const screen = render(() => <App />, { location: '/' })
setIsHydrating(false)

// Act
// TODO:
// press play on the time entry with the respective id
// move time forward
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })
fireEvent.click(currentTimerStartButton)

// Assert
// TODO:
// assert that current timer displays correct time entry
expect(true).toBe(true)
})
it('should run on toggle start', async () => {
// Arrange
// TODO:
// fill store with a time entry
const screen = render(() => <App />, { location: '/' })
setIsHydrating(false)

// Act
// TODO:
// press play on the time entry with the respective id
// move time forward
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })
fireEvent.click(currentTimerStartButton)

// Assert
// TODO:
// assert that current timer displays correct time entry
expect(true).toBe(true)
})
And here's the top level component I am testing:
const App = () => {
return (
<Routes>
<Route path="/" component={Overview} />
<Route path="/projects" component={Projects} />
<Route path="/settings" component={Settings} />
</Routes>
)
}
export default App
const App = () => {
return (
<Routes>
<Route path="/" component={Overview} />
<Route path="/projects" component={Projects} />
<Route path="/settings" component={Settings} />
</Routes>
)
}
export default App
33 replies
SSolidJS
Created by oneiro on 6/26/2023 in #support
Solid-testing library TS-eslint-errors
Hey< I am just starting out using solids testing library and setup my project according to this example: https://github.com/solidjs/solid-start/tree/main/examples/with-vitest/src However I am getting some TS-errors I am not quite sure how to resolve correctly. My Counter.test.tsx looks exactly like in the example:
import { fireEvent, render } from "@solidjs/testing-library";
import Counter from "./Counter";

describe("<Counter />", () => {
it("increments value", async () => {
const { queryByRole, unmount } = render(() => <Counter />);
const button = (await queryByRole("button")) as HTMLButtonElement;
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent(/Clicks: 0/);
fireEvent.click(button);
expect(button).toHaveTextContent(/Clicks: 1/);
unmount();
});

it("renders 1", () => {
const { container, unmount } = render(() => <Counter />);
expect(container).toMatchSnapshot();
unmount();
});
});
import { fireEvent, render } from "@solidjs/testing-library";
import Counter from "./Counter";

describe("<Counter />", () => {
it("increments value", async () => {
const { queryByRole, unmount } = render(() => <Counter />);
const button = (await queryByRole("button")) as HTMLButtonElement;
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent(/Clicks: 0/);
fireEvent.click(button);
expect(button).toHaveTextContent(/Clicks: 1/);
unmount();
});

it("renders 1", () => {
const { container, unmount } = render(() => <Counter />);
expect(container).toMatchSnapshot();
unmount();
});
});
However on the destructor of queryByRole I receive the following error:
Avoid referencing unbound methods which may cause unintentional scoping of `this`.
If your function does not access `this`, you can annotate it with `this: void`, or consider using an arrow function instead. [@typescript-eslint/unbound-method]
Avoid referencing unbound methods which may cause unintentional scoping of `this`.
If your function does not access `this`, you can annotate it with `this: void`, or consider using an arrow function instead. [@typescript-eslint/unbound-method]
Furhtermore on the call to queryByRole I receive an error, that queryByRole does not return a Promise and is therefore not awaitable. Is this an error on my part or is this an error already present inside the example repo? Thanks in advance
11 replies
SSolidJS
Created by oneiro on 6/26/2023 in #support
Solid-start client side state best practices
Hey folks, I noticed that the docs are still missing the section on the various kinds of application state. Therefore I wanted to ask here what is considere to be a good approach to handle state after hydration. Example: We use createServerData to build our initial route data. But after hydration we would like to have the state globally available. What would be the best approach to do this? Should we simply take the data and put it in a store or is there another recommended approach? Thanks in advance
3 replies
SSolidJS
Created by oneiro on 6/14/2023 in #support
How "beta" is SolidStart?
Hey, sorry for the weird phrasing of the question. I am currently starting a new small customer project and was wondering if it would be worth checking out solidStart for this. However the beta disclaimer (while appreciated) is a bit discouraging. Would you say that solidstart is already usable enough for a real world project and that APIs are somewhat stable, or will I shoot myself in the foot by using it right now? If the latter is the case, are there other recommended approaches to do SSR with Solid right now? Thanks in advance
3 replies
SSolidJS
Created by oneiro on 6/11/2023 in #support
Confused about resource mutation with `createDeepSignal` and `produce`
Hey folks, I am trying to create a resource which gets updated on a button click, by fetching content from a server. However the user may change parts of the data they have already fetched. When refetching the data, we want to make sure that all user changes are not being overwritten. To allow changing small parts of the data and still being reactive, I use createDeepSignal from solid-primitives. My resource is initiated like this:
export const [projectsFromStore, { refetch: reloadProjects, mutate: mutateProjects }] = createResource(loadProjects, {
storage: createDeepSignal,
})
export const [projectsFromStore, { refetch: reloadProjects, mutate: mutateProjects }] = createResource(loadProjects, {
storage: createDeepSignal,
})
Store here is a persisted file. By default this file is empty until the user fetches projects from a remote server for the first time. This fetch function can be used repeatedly and should alter its behaviour depending on if the user already has fetched projects or not as described above. My fetch function looks like this: (continuation in comment)
20 replies