Tìm kiếm trang web

reactjs - hàm state của zustand để thay đổi một thuộc tính của đối tượng


Vì vậy, tôi đang sử dụng Zustand với React trong ứng dụng Electron của mình. Tôi đang sử dụng nó để lấy một số dữ liệu từ cơ sở dữ liệu Dexie. Chỉ là một mục và nó lưu vào state. Tôi đang cố gắng lấy hàm set từ component render để có thể thay đổi state của thuộc tính tương ứng trong state. Trong React useState, mã này hoạt động...

setMyState({...appSettings, [val]: data})

nhưng trong zustand trạng thái của tôi trông như thế này và mã này không hoạt động

setAppSettings: (data: unknown, val: string) => {
        set((state) => ({...state.appSettings, [val]: data}))
}

Webstorm đang báo cho tôi "Argument of type is not assignable to parameter of type". Tôi đã đổi kiểu dữ liệu của "data" thành any nhưng không có tác dụng gì. Khi tôi chạy mã này và nhấn vào nút để thay đổi, không có gì xảy ra, thậm chí không có lỗi. Tôi đã đổi nó thành mã này với cùng kết quả, vẫn không có gì xảy ra.

setAppSettings: (data: any, val: string) => {
        set((state) => ({
            appSettings: {...state.appSettings, [val]: data}
        }))
},

Với đoạn mã thứ hai này, tôi không gặp lỗi gì trong Webstorm. Vì vậy, không rõ chuyện gì đang xảy ra vì console không hiển thị gì cả. Ngoài ra, trạng thái dường như không được cập nhật. Tôi thêm một nút mà console.log toàn bộ đối tượng 'appSettings' và nó vẫn không thay đổi.

Tôi cảm thấy đây là một giải pháp đơn giản nhưng tôi đã đau đầu để tìm ra điều này... Có ai có hiểu biết gì về vấn đề này không?

------Chỉnh sửa cho câu trả lời đầu tiên Tôi không chắc kiểu dữ liệu có phải là vấn đề không? Tôi nghĩ vấn đề là tôi không quen lắm với cách zustand hoạt động? nhưng hàm cố gắng lưu trạng thái là...

// 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>
  )
}

Câu trả lời #1

Vậy trong trường hợp đầu tiên:

setAppSettings: (data: unknown, val: string) => {
        set((state) => ({...state.appSettings, [val]: data}))
}

Về cơ bản, những gì xảy ra là trạng thái của bạn có một số type như RootState, AppState hoặc bất cứ thứ gì.

Và

Webstorm is telling me "Argument of type is not assignable to parameter of type". 

Ý nghĩa là, khi bạn có setter [key] như vậy, TypeScript không thể ép kiểu [key:string]: unknown sang kiểu của state của bạn, nên nó sẽ báo lỗi Argument of type is not assignable

Để tránh điều đó, bạn có thể thêm as any nhưng không phải vào data, mà vào kết quả của hàm

setAppSettings: (data: unknown, val: string) => {
        set((state) => ({...state.appSettings, [val]: data} as any))
}

Về cơ bản, đối tượng được trả về bởi (state) => nên là typeof (state)

Có những cách giải quyết, như sử dụng as const, enums, typeof keyof, nhưng cần nhiều mã hơn của bạn để đưa ra câu trả lời chính xác...

Cập nhật

Đây là lỗi của bạn:

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) => ...

Và đây là một đoạn mã hoạt động:

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);

Đã sửa thêm một lỗi nữa.

Bài viết liên quan