reactjs - دالة حالة في zustand لتغيير خاصية واحدة من كائن
لذلك أنا أستخدم Zustand مع React في تطبيق Electron الخاص بي. أنا أستخدمه لاسترجاع بعض البيانات من قاعدة بيانات Dexie. إنها مجرد مدخلة واحدة ويتم حفظها في الحالة. أحاول الحصول على دالة set من مكون الرندر لأتمكن من تغيير حالة الخاصية الخاصة بها في الحالة. في React useState هذا الكود يعمل...
setMyState({...appSettings, [val]: data})
ولكن في Zustand حالتي تبدو هكذا وهذا الكود لا يعمل
setAppSettings: (data: unknown, val: string) => {
set((state) => ({...state.appSettings, [val]: data}))
}
ويب ستورم يخبرني بـ "نوع المعامل غير قابل للإسناد إلى نوع المعامل". لقد قمت بتغيير نوع "البيانات" إلى أي نوع ولم يكن لذلك أي تأثير. عندما أقوم بتشغيل هذا الكود والنقر على الزر لتغييره، لا يحدث شيء، ولا حتى خطأ. لقد غيرته إلى هذا الكود بنفس النتيجة، لا يحدث شيء.
setAppSettings: (data: any, val: string) => {
set((state) => ({
appSettings: {...state.appSettings, [val]: data}
}))
},
مع هذا الكود الثاني لا أحصل على أي أخطاء في Webstorm. لذا من غير الواضح ما الذي يحدث حيث أن وحدة التحكم لا تعطيني أي شيء. أيضًا، يبدو أن الحالة لا تتغير. أضفت زرًا يقوم بعرض الكائن 'appSettings' بأكمله في وحدة التحكم ولا يتغير.
أشعر أن هذا حل بسيط لكني كنت أضرب رأسي بالحائط لمحاولة معرفة هذا... هل لدى أي شخص أي فكرة عن هذا؟
------تحرير للإجابة الأولى لست متأكدًا من أن نوع البيانات هو المشكلة؟ أعتقد أن السبب هو أنني لست ملمًا بكيفية عمل zustand؟ لكن الوظيفة التي تحاول حفظ الحالة هي...
// store.ts
type AppSettings = {
appSettings: Settings;
setAppSettings: (role: string, data: unknown) => void;
getAppSettings: () => void;
}
export const useAppSettings = create<AppSettings>((set) => ({
appSettings: {
id: 0,
sortByTime: false,
sortByFirstName: false,
colorMode: '',
hours: 24,
},
setAppSettings: (role: string, data: unknown) => {
set((state) => ({
appSettings: {...state.appSettings, [role]: data}
}))
},
getAppSettings: async () => {
const result = await db.settings.toCollection().first();
if (result === undefined) {
console.log("No settings in db, using default")
} else {
set(() => ({appSettings: result}))
}
},
}))
//Interface for settings object - in another file
export interface Settings {
id: number,
sortByTime: boolean,
sortByFirstName: boolean,
colorMode: string,
hours: number,
}
// This buttonCreate function is used to duplicate 4 buttons that
// all look alike and have the same operation.
const setSettings = useAppSettings((state) => state.setAppSettings)
const buttonCreate = (forRole: string, con1: any, con2: any) => {
return (
<ToggleButtonGroup type="radio" name={forRole} className="mb-2 warning" value={settings[forRole]}>
<ToggleButton id={forRole + "-toggle-1"} value={con1}
className={"btn-dark"} onClick={() => setSettings(forRole, con1)}>
{typeof con1 === "boolean" ? "Yes" : con1}
</ToggleButton>
<ToggleButton id={forRole + "-toggle-2"} value={con2}
className={"btn-dark"} onClick={() => setSettings(forRole, con2)}>
{typeof con2 === "boolean" ? "No" : con2}
</ToggleButton>
</ToggleButtonGroup>
)
}
الإجابة رقم 1
إذاً في الحالة الأولى:
setAppSettings: (data: unknown, val: string) => {
set((state) => ({...state.appSettings, [val]: data}))
}
بشكل أساسي ما يحدث هو أن حالتك لها نوع معين مثل RootState، AppState أو أي شيء آخر.
و
Webstorm is telling me "Argument of type is not assignable to parameter of type".
ماذا يعني ذلك، أنه عندما يكون لديك مُعيّن [key] بهذا الشكل لا يستطيع TypeScript تحويل [key:string]: unknown إلى نوع الحالة لديك، لذلك يعطيك Argument of type is not assignable
لتجنب ذلك، يمكنك إضافة as any لكن ليس إلى data، بل إلى نتيجة الدالة
setAppSettings: (data: unknown, val: string) => {
set((state) => ({...state.appSettings, [val]: data} as any))
}
بشكل أساسي، الكائن الذي يتم إرجاعه بواسطة (state) => يجب أن يكون typeof (state)
هناك طرق لتجنب ذلك، مثل استخدام as const، enums، typeof keyof، لكن يحتاج ذلك إلى مزيد من كودك لتقديم إجابة مناسبة...
تحديث
هناك خطؤك:
export type AppSettings = {
appSettings: Settings;
setAppSettings: (data: Settings, val: string) => void; // << data: Settings
getAppSettings: () => void;
};
// and then you override type:
setAppSettings: (data: unknown, val: string) => ...
وهناك لديك كود يعمل:
import { create } from "zustand";
import createSelectors from "./selectors";
export type AppSettings = {
appSettings: Settings;
setAppSettings: (data: unknown, val: string) => void;
getAppSettings: () => void;
};
interface Settings {
id: number;
sortByTime: boolean;
sortByFirstName: boolean;
colorMode: string;
hours: number;
}
const appSettings = create<AppSettings>()((set) => ({
appSettings: {
id: 1,
sortByTime: false,
sortByFirstName: false,
colorMode: "",
hours: 0,
},
// u also had error here:
setAppSettings: (data, val) =>
set((state) => ({
...state, // u need pass state here...
appSettings: { ...state.appSettings, [val]: data },
})),
getAppSettings: () => {},
}));
export const useAppSettings = createSelectors(appSettings);
تم إصلاح خطأ آخر.
