Best Practice for ContextProvider - Store vs Signals

When making a context provider is it best practice to use a store instead of several individual signals or does it not matter? E.g
interface Props {
children: JSX.Element;
}

export interface IGlobalStore {
carType: string;
modelYear: number;
warrentyNumber: number;
carColor: string[];
}

interface GlobalContextValues extends IGlobalStore {
setState: SetStoreFunction<IGlobalStore>
}

export const GlobalContext = createContext<GlobalContextValues>(
{
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
setState: () => {},
}
);

export function GlobalProvider(props: Props) {
const [state, setState] = createStore<IGlobalStore>({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
});

let isCarMade = true;
const setCarBeingMade = (value: boolean) => {
isCarMade = value;
}

const context = {
// Global
get carType(){ return state.carType},
get modelYear(){ return state.modelYear},
get warrentyNumber(){ return state.warrentyNumber},
get carColor(){ return state.carColor},
setState,

get isCarMade() {
return isCarMade;
},
setCarBeingMade,
}

return (
<GlobalContext.Provider value={context}>
{props.children}
</GlobalContext.Provider>
);
}

export function useGlobalContext() {
return useContext(GlobalContext);
}
interface Props {
children: JSX.Element;
}

export interface IGlobalStore {
carType: string;
modelYear: number;
warrentyNumber: number;
carColor: string[];
}

interface GlobalContextValues extends IGlobalStore {
setState: SetStoreFunction<IGlobalStore>
}

export const GlobalContext = createContext<GlobalContextValues>(
{
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
setState: () => {},
}
);

export function GlobalProvider(props: Props) {
const [state, setState] = createStore<IGlobalStore>({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
});

let isCarMade = true;
const setCarBeingMade = (value: boolean) => {
isCarMade = value;
}

const context = {
// Global
get carType(){ return state.carType},
get modelYear(){ return state.modelYear},
get warrentyNumber(){ return state.warrentyNumber},
get carColor(){ return state.carColor},
setState,

get isCarMade() {
return isCarMade;
},
setCarBeingMade,
}

return (
<GlobalContext.Provider value={context}>
{props.children}
</GlobalContext.Provider>
);
}

export function useGlobalContext() {
return useContext(GlobalContext);
}
OR
3 Replies
Carlo Nyte
Carlo Nyte11mo ago
This:
export const GlobalContext = createContext();

export function GlobalProvider(props: Props) {
const [carType, setCarType] = createSignal<string>('');
const [modelYear, setModelYear] = createSignal<number>(0);
const [warrentyNumber, setWarrentyNumber] = createSignal<number>(0);
const [carColor, setCarColor] = createSignal<string[]>([]);

let isCarMade = false;
const setCarBeingMade = (value: boolean) => {
isCarMade = value;
}

const context = {
// Global
carType: [carType, setCarType],
modelYear: [modelYear, setModelYear],
warrentyNumber: [warrentyNumber, setWarrentyNumber],
carColor: [carColor, setCarColor],

get isCarMade() {
return isCarMade;
},
setCarBeingMade,
}

return (
<GlobalContext.Provider value={context}>
{props.children}
</GlobalContext.Provider>
);
}

export function useGlobalContext() {
return useContext(GlobalContext);
}
export const GlobalContext = createContext();

export function GlobalProvider(props: Props) {
const [carType, setCarType] = createSignal<string>('');
const [modelYear, setModelYear] = createSignal<number>(0);
const [warrentyNumber, setWarrentyNumber] = createSignal<number>(0);
const [carColor, setCarColor] = createSignal<string[]>([]);

let isCarMade = false;
const setCarBeingMade = (value: boolean) => {
isCarMade = value;
}

const context = {
// Global
carType: [carType, setCarType],
modelYear: [modelYear, setModelYear],
warrentyNumber: [warrentyNumber, setWarrentyNumber],
carColor: [carColor, setCarColor],

get isCarMade() {
return isCarMade;
},
setCarBeingMade,
}

return (
<GlobalContext.Provider value={context}>
{props.children}
</GlobalContext.Provider>
);
}

export function useGlobalContext() {
return useContext(GlobalContext);
}
lvl_up
lvl_up11mo ago
I'd would opt for the store option. Stores can provide a much simpler syntax/experience to work with multiple properties like you have here. Stores also provide a lot of useful utility functions https://docs.solidjs.com/references/api-reference/stores/store-utilities
export function ContextProvider(props) {
const [state, setState] = createStore({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
});

return (
<GlobalContext.Provider value={{ state, setState }}>
{props.children}
</GlobalContext.Provider>
);
}

const { state, setState } = useContext(GlobalContext);

// get store value
state.carType

// set store value
setState('carType', newValue);
export function ContextProvider(props) {
const [state, setState] = createStore({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
});

return (
<GlobalContext.Provider value={{ state, setState }}>
{props.children}
</GlobalContext.Provider>
);
}

const { state, setState } = useContext(GlobalContext);

// get store value
state.carType

// set store value
setState('carType', newValue);
It's also much easier to add a property to the store than having to create a new signal for each
export function ContextProvider(props) {
const [state, setState] = createStore({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
// new property
newProperty: ''
});
}

export function ContextProvider(props) {
const [newProperty, setNewProperty] = createSignal('');

// ... pass signal to context
}
export function ContextProvider(props) {
const [state, setState] = createStore({
carType: '',
modelYear: 0,
warrentyNumber: 0,
carColor: [],
// new property
newProperty: ''
});
}

export function ContextProvider(props) {
const [newProperty, setNewProperty] = createSignal('');

// ... pass signal to context
}
Carlo Nyte
Carlo Nyte11mo ago
Appreciate this thank you