Untlsn
Untlsn
SSolidJS
Created by Untlsn on 10/29/2024 in #support
[h3] [unhandled] TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["X-Error"]
encodeURI and encodeURIComponent work the same in that case From little testing special characters like /?: aren't throwing this error So probably encodeURI is slightly better because it encode less characters, but i don't know
5 replies
SSolidJS
Created by Untlsn on 10/29/2024 in #support
[h3] [unhandled] TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["X-Error"]
Or even better and probably correct answer Just encode message before sending and decode before displaying
5 replies
SSolidJS
Created by Untlsn on 10/29/2024 in #support
[h3] [unhandled] TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["X-Error"]
I founded temporary workaround If I wrap error with json function it return X-Error as true and error in body without issue
5 replies
SSolidJS
Created by Untlsn on 10/29/2024 in #support
[h3] [unhandled] TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["X-Error"]
After some digging i find out that this error is more helpful then expected This error is thrown when i used special letter in message (in my case Polish ł and ą in word "Błąd") Maybe there is a way to remove X-Error or change it to true like when throwing json with status >= 400?
5 replies
SSolidJS
Created by macrbe on 9/14/2024 in #support
App Structure
And selected products with localStorage sync
/**
* Create signal that get inital data from localStorage and sync data with it on every change
*/
function createLocalStorageSync<T>(key: string, transformIn: (value: string | null) => T, transformOut: (value: T) => string) {
const selectedProductsKeys = localStorage.getItem('selectedProductsKeys');

const [value, setValue] = createSignal<T>(
transformIn(selectedProductsKeys),
);

return [
value,
(setter: Exclude<T, Function> | ((prev: T) => T)) => {
setValue(setter);
transformOut(untrack(value));
},
] as const;
}

/**
* Controller for selected products.
*
*/
function useSelectedProducts() {
const [cache] = useProductCache();

const [selectedProducts, setSelectedProducts] = createLocalStorageSync(
'selectedProductsKeys',
(value) => value?.split(';').map((key) => {
const [category, productSlug] = key.split('_');
useProductFetcher(category, productSlug);
return key;
}) || [],
(arr) => arr.join(';'),
);

return [
() => selectedProducts().map((key) => cache[key]),
{
addProduct(category: string, productSlug: string) {
setSelectedProducts((old) => [...old, createProductKey(category, productSlug)]);
},
removeProduct(index: number) {
setSelectedProducts((old) => old.toSpliced(index, 1));
},
clear() {
setSelectedProducts([]);
},
},
];
}
/**
* Create signal that get inital data from localStorage and sync data with it on every change
*/
function createLocalStorageSync<T>(key: string, transformIn: (value: string | null) => T, transformOut: (value: T) => string) {
const selectedProductsKeys = localStorage.getItem('selectedProductsKeys');

const [value, setValue] = createSignal<T>(
transformIn(selectedProductsKeys),
);

return [
value,
(setter: Exclude<T, Function> | ((prev: T) => T)) => {
setValue(setter);
transformOut(untrack(value));
},
] as const;
}

/**
* Controller for selected products.
*
*/
function useSelectedProducts() {
const [cache] = useProductCache();

const [selectedProducts, setSelectedProducts] = createLocalStorageSync(
'selectedProductsKeys',
(value) => value?.split(';').map((key) => {
const [category, productSlug] = key.split('_');
useProductFetcher(category, productSlug);
return key;
}) || [],
(arr) => arr.join(';'),
);

return [
() => selectedProducts().map((key) => cache[key]),
{
addProduct(category: string, productSlug: string) {
setSelectedProducts((old) => [...old, createProductKey(category, productSlug)]);
},
removeProduct(index: number) {
setSelectedProducts((old) => old.toSpliced(index, 1));
},
clear() {
setSelectedProducts([]);
},
},
];
}
5 replies
SSolidJS
Created by macrbe on 9/14/2024 in #support
App Structure
product fetch:
/**
* Convert category and productSlug to universal key
*/
function createProductKey(category: string, productSlug: string) {
return `${category}_${productSlug}`;
}

/**
* Mainly for internal usage
* Fetch product and add it to cache even if product is present in cache
*/
function useProductFetcher(category: string, productSlug: string) {
const [, setCache] = useProductCache();

const [data, { refetch }] = createResource(
() => ({ category, productSlug }),
fetchProduct,
);
setCache(createProductKey(category, productSlug), { data, refetch });
}

/**
* Get product based on category and productSlug
* It will handle caching new data;
*/
function useFetchFullProduct(category: string, productSlug: string) {
const [cache] = useProductCache();

const key = createProductKey(category, productSlug);

untrack(() => {
if (!cache[key]) useProductFetcher(category, productSlug);
});

return () => cache[key];
}
/**
* Convert category and productSlug to universal key
*/
function createProductKey(category: string, productSlug: string) {
return `${category}_${productSlug}`;
}

/**
* Mainly for internal usage
* Fetch product and add it to cache even if product is present in cache
*/
function useProductFetcher(category: string, productSlug: string) {
const [, setCache] = useProductCache();

const [data, { refetch }] = createResource(
() => ({ category, productSlug }),
fetchProduct,
);
setCache(createProductKey(category, productSlug), { data, refetch });
}

/**
* Get product based on category and productSlug
* It will handle caching new data;
*/
function useFetchFullProduct(category: string, productSlug: string) {
const [cache] = useProductCache();

const key = createProductKey(category, productSlug);

untrack(() => {
if (!cache[key]) useProductFetcher(category, productSlug);
});

return () => cache[key];
}
5 replies
SSolidJS
Created by macrbe on 9/14/2024 in #support
App Structure
Cache:
type ProductCacheItem = { data: Resource<FullProduct>, refetch: () => void };
type ProductCache = Record<string, ProductCacheItem>;

const ProductCacheContext = createContext<[get: Store<ProductCache>, set: SetStoreFunction<ProductCache>]>();

function ProductCacheProvider(props: FlowProps) {
return (
<ProductCacheContext.Provider value={createStore({})}>
{props.children}
</ProductCacheContext.Provider>
);
}

function useProductCache() {
const context = useContext(ProductCacheContext);
if (!context) throw new Error('ProductCacheProvider must be used in component tree');
return context;
}
type ProductCacheItem = { data: Resource<FullProduct>, refetch: () => void };
type ProductCache = Record<string, ProductCacheItem>;

const ProductCacheContext = createContext<[get: Store<ProductCache>, set: SetStoreFunction<ProductCache>]>();

function ProductCacheProvider(props: FlowProps) {
return (
<ProductCacheContext.Provider value={createStore({})}>
{props.children}
</ProductCacheContext.Provider>
);
}

function useProductCache() {
const context = useContext(ProductCacheContext);
if (!context) throw new Error('ProductCacheProvider must be used in component tree');
return context;
}
5 replies
SSolidJS
Created by macrbe on 9/14/2024 in #support
App Structure
So you need to move your cache to global or to context and i sugest to make it store, so if you refetch then everythink subscribe to data will be notified. Assumption: You don't use SSR Maybe this will give you some ideas:
5 replies
SSolidJS
Created by Untlsn on 9/11/2024 in #support
Sugestion for Repeat component
4 replies
SSolidJS
Created by radek1313 on 9/11/2024 in #support
dev server pending forever request solid start
Are you useing any async stuff? Maybe one promise is in constant pending state and whole app just wait for it to settle If yes, then try to add fallback to root suspense. If this fallback is present then it's propably it Simple example of how constant pending looks like: https://playground.solidjs.com/anonymous/ae8218b5-3203-4b8f-b938-f7f9c6177173
3 replies