S
SolidJS•2y ago
D0Z

Type 'StoreState | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.

I'm trying to setup a simple context provider plz help 😦
import { createContext, ParentComponent, useContext } from 'solid-js'
import { createStore } from 'solid-js/store'

import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'

/**
* Store type
*/
type StoreState = [
{ socket: boolean | Socket },
{
set?: (
url: string,
options: Partial<ManagerOptions & SocketOptions>
) => void
}
]

/**
* Initial state of the store
*/
const initialState = {
socket: false
}

/**
* Context
*/
const SocketIoContext = createContext<StoreState>()

/**
* Socket provider
*/
export const SocketIoProvider: ParentComponent = (props) => {
const [state, setState] = createStore<StoreState[0]>(initialState)

const store: StoreState = [
state,
{
set: (
url = window._env ? window._env.SOCKET_URL : 'http://localhost/4000',
options: Partial<ManagerOptions & SocketOptions>
) => {
setState('socket', io(url, options))
}
}
]

return (
<SocketIoContext.Provider value={store}>
{props.children}
</SocketIoContext.Provider>
)
}

const useSocketIo = () => useContext(SocketIoContext)

export default useSocketIo
import { createContext, ParentComponent, useContext } from 'solid-js'
import { createStore } from 'solid-js/store'

import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'

/**
* Store type
*/
type StoreState = [
{ socket: boolean | Socket },
{
set?: (
url: string,
options: Partial<ManagerOptions & SocketOptions>
) => void
}
]

/**
* Initial state of the store
*/
const initialState = {
socket: false
}

/**
* Context
*/
const SocketIoContext = createContext<StoreState>()

/**
* Socket provider
*/
export const SocketIoProvider: ParentComponent = (props) => {
const [state, setState] = createStore<StoreState[0]>(initialState)

const store: StoreState = [
state,
{
set: (
url = window._env ? window._env.SOCKET_URL : 'http://localhost/4000',
options: Partial<ManagerOptions & SocketOptions>
) => {
setState('socket', io(url, options))
}
}
]

return (
<SocketIoContext.Provider value={store}>
{props.children}
</SocketIoContext.Provider>
)
}

const useSocketIo = () => useContext(SocketIoContext)

export default useSocketIo
and use it in a component
const Space = () => {
const [socket, { set }] = useSocketIo()
return <>{socket}BRUH</>
}
const Space = () => {
const [socket, { set }] = useSocketIo()
return <>{socket}BRUH</>
}
but const [socket, { set }] = useSocketIo() gives me an error
18 Replies
thetarnav
thetarnav•2y ago
useContext returns T | undefined by default because the context might be missing. And you cannot destructure an undefined useContext accepts a second value that will be used as a fallback or so this
D0Z
D0Z•2y ago
ryansolid
CodeSandbox
Counter Context - CodeSandbox
Counter Context by ryansolid using babel-preset-solid, solid-js
thetarnav
thetarnav•2y ago
const useSocketIo = () => {
const ctx = useContext(SocketIoContext)
if (!ctx) throw new Error("no context 0.0")
return ctx
}
const useSocketIo = () => {
const ctx = useContext(SocketIoContext)
if (!ctx) throw new Error("no context 0.0")
return ctx
}
D0Z
D0Z•2y ago
ooh noice
thetarnav
thetarnav•2y ago
this example is better (better ts) https://www.solidjs.com/examples/context
SolidJS
Solid is a purely reactive library. It was designed from the ground up with a reactive core. It's influenced by reactive principles developed by previous libraries.
D0Z
D0Z•2y ago
you're da MVP damn wait I'm dumb I missed this section on the website 😂 thanks for your time ! hum okay everything work but if I initialize the socket to false I get a new error
D0Z
D0Z•2y ago
D0Z
D0Z•2y ago
even worse if I set the type to false | Socket I get an error at createContext full code
import { createContext, ParentComponent, useContext } from 'solid-js'
import { createStore } from 'solid-js/store'

import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'

/**
* Store type
*/
type StoreState = {
readonly socket: false | Socket
}

/**
* Context type
*/
type ContextState = [
state: StoreState,
actions: {
set?: (
url: string,
options: Partial<ManagerOptions & SocketOptions>
) => void
}
]

/**
* Initial state of the store
*/
const initialState = {
socket: false
}

/**
* Context
*/
const SocketIoContext = createContext<ContextState>([
initialState,
{ set: () => undefined }
])

/**
* Provider
*/
export const SocketIoProvider: ParentComponent = (props) => {
const [state, setState] = createStore(initialState)

const set = (
url = window._env.SOCKET_URL || 'http://localhost/4000',
options: Partial<ManagerOptions & SocketOptions>
) => {
setState('socket', io(url, options))
}

return (
<SocketIoContext.Provider value={[state, { set }]}>
{props.children}
</SocketIoContext.Provider>
)
}

const useSocketIo = () => useContext(SocketIoContext)

export default useSocketIo
import { createContext, ParentComponent, useContext } from 'solid-js'
import { createStore } from 'solid-js/store'

import { io, ManagerOptions, Socket, SocketOptions } from 'socket.io-client'

/**
* Store type
*/
type StoreState = {
readonly socket: false | Socket
}

/**
* Context type
*/
type ContextState = [
state: StoreState,
actions: {
set?: (
url: string,
options: Partial<ManagerOptions & SocketOptions>
) => void
}
]

/**
* Initial state of the store
*/
const initialState = {
socket: false
}

/**
* Context
*/
const SocketIoContext = createContext<ContextState>([
initialState,
{ set: () => undefined }
])

/**
* Provider
*/
export const SocketIoProvider: ParentComponent = (props) => {
const [state, setState] = createStore(initialState)

const set = (
url = window._env.SOCKET_URL || 'http://localhost/4000',
options: Partial<ManagerOptions & SocketOptions>
) => {
setState('socket', io(url, options))
}

return (
<SocketIoContext.Provider value={[state, { set }]}>
{props.children}
</SocketIoContext.Provider>
)
}

const useSocketIo = () => useContext(SocketIoContext)

export default useSocketIo
I think maybe I should start from scratch and actually learn how this framework works... I might be trying to do stuff like I used to with react... for ex my process with this before was: a user login -> we get the authToken and store it -> redirect the user to the protected parts, then use this token to configure the socket globally on the app with zustand using a hook that expose methods to initialize the socket then connect to it
thetarnav
thetarnav•2y ago
createStore<{ socket: boolean | TypeOfTheSocketThing }>(initialState) store infers it as boolean only from the initial value or use the StoreState or new ts 4.9 satisfying syntax
const initialState = {
socket: false
} as const satisfies StoreState
const initialState = {
socket: false
} as const satisfies StoreState
D0Z
D0Z•2y ago
man this is black magic yeah I'm dumb... Man I though that it was gonna be easier since the syntax is close to react 😂 I'm lost but thankfully you're here
thetarnav
thetarnav•2y ago
not sure how context works in react, but I know that typescript works the same way... reading and understanding ts errors will help you in every framework
D0Z
D0Z•2y ago
Well I was relying entirely on zustand, and indeed using different frameworks will help to understand new stuff, and solid might actually be the one where I will learn the most it seems 😂
thetarnav
thetarnav•2y ago
I guess zustand might be guiding you better solid just gives you a couple of primitives and says have fun
D0Z
D0Z•2y ago
Well for zustand it's pretty much basic object manipulation, so you define the type once and voila also where I needed to do specific stuff with types was pretty centralized since I would use only one createStore so I had to do "weird" manipulation once and it would simplify my type declaration everywhere as I import my slices onto the store and yeah there wasn't much to play around either, pretty much straight forward
thetarnav
thetarnav•2y ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
D0Z
D0Z•2y ago
lmao you actually did it 😂 But I asked in general and it wasn't really useful since Solid is pretty good for state management, the implementation is interesting nontheless wait what I though you actually used zustand but no
thetarnav
thetarnav•2y ago
it is pointless, this was just to prove a point
D0Z
D0Z•2y ago
man 😂 yeah solid is indeed amazing for state management, I'm really happy I stubbled upon it