Jadi saya memiliki pengait yang terpasang, membaca data dari indexedDB dan menyimpan data itu dalam keadaan internalnya

Masalah yang saya miliki, adalah bahwa data indexedDB diubah dari komponen lain (ditambahkan/dihapus), dan saya perlu bereaksi terhadap perubahan tersebut di hook ini. Saya tidak 100% akrab dengan kait dan bagaimana ini akan dilakukan, tetapi pikiran pertama adalah memiliki ketergantungan kait nilai dari indexedDB.

NAMUN, pembacaan data dari indexedDB adalah operasi async dan ketergantungan hook akan menjadi.. janji.

Jadi pada dasarnya, alurnya adalah sebagai berikut:

  1. Komponen 1 memanggil hook seperti ini:
  const eventItems = useEventListItems({
    sortBy,
    sortGroupedBy,
    eventTimestamp,
    events,
    assets,
    touchedEventIds,
    unsyncedEvents, // <--- this is the one that we need
    order,
  });
  1. Kait useEventListItems, saat dipasang, membaca data dari DB yang diindeks, menyimpannya dalam keadaan internal dan mengembalikannya:
  const { readUnsyncedEvents } = useDebriefStore();
  const [unsyncedEvents, setUnsyncedEvents] = useState<number[]>([]);
  useEffectAsync(async () => {
    const storedUnsyncedEventIds = await readUnsyncedEvents<number[]>();
    if (storedUnsyncedEventIds?.data) {
      setUnsyncedEvents(storedUnsyncedEventIds.data);
    }
  }, [setUnsyncedEvents]);

Di mana readUnsyncedEvents adalah:

export const readUnsyncedEvents = <T>(type: Type): Promise<DebriefStoreEntry<T>> =>
  debriefStore
    .get(type)
    .then((entry) => entry && { data: entry.data, timestamp: entry.timestamp });
  1. UnsyncedEvents dari indexedDB kemudian diubah dari komponen lain.

  2. Apa yang seharusnya terjadi sekarang, adalah bahwa kait useEventListItems harus mendengarkan perubahan di IDB dan memperbarui unsyncedEvents dalam keadaan internalnya, meneruskannya ke komponen yang menggunakan kait ini. Bagaimana saya akan mencapai ini?

Pikiran pertama saya adalah memiliki sesuatu seperti ini di kait useEventListItems:

useEffect(() => {
  setUnsyncedEvents(..newValueFromIdb);
}, [ await readUnsyncedEvents()]);

Tapi itu tidak akan berhasil karena itu akan menjadi janji. Apakah ada yang bisa saya miliki sebagai ketergantungan kait, nilai yang dikembalikan oleh operasi async?

0
bamtheboozle 10 Juli 2020, 11:43

1 menjawab

Jawaban Terbaik

Anda dapat menggunakan API Konteks untuk mengambil kembali data dari IDB.

Idenya di sini adalah untuk membuat konteks dengan variabel penghitung yang akan diperbarui setelah setiap operasi pembaruan IDB. Dan kait useEventListItems akan membaca variabel penghitung itu dari konteks dan memicu kait useEffect.

export const IDBContext = React.createContext({
  readFromIDB: null,
  setReadFromIDB: () => {}
});

export const IDBContextProvider = ({ children }) => {
  const [readFromIDB, setReadFromIDB] = useState(0);
  return (
    <IDBContext.Provider value={{ readFromIDB, setReadFromIDB }}>
      {children}
    </IDBContext.Provider>
  );
};  

Beginilah tampilan useEventListItems Anda.

const { readUnsyncedEvents } = useDebriefStore();
const [unsyncedEvents, setUnsyncedEvents] = useState<number[]>([]);

const {readFromIDB} = useContext(IDBContext); // this variable will be updated after each IDB update.

useEffectAsync(async () => {
  const storedUnsyncedEventIds = await readUnsyncedEvents<number[]>();
  if (storedUnsyncedEventIds?.data) {
    setUnsyncedEvents(storedUnsyncedEventIds.data);
  }
}, [readFromIDB,setUnsyncedEvents]); // added that to dependency array to trigger the hook on value change.

Dan berikut adalah komponen-komponennya:

const IDBUpdateComponent = ()=>{
const {readFromIDB,setReadFromIDB} = useContext(IDBContext);
  const updateIDB = ()=>{
    someIDBUpdateOpetation().then(res=>{
      setReadFromIDB(readFromIDB+1) // update the context after IDB update is successful.
    }).catch(e=>{})
  }

  return(
    <div>IDBUpdateComponent</div>
  );
}

const IDBConsumerComponent = ()=>{
  return (
    <div>IDBConsumerComponent</div>
  )
}

Pastikan saja kedua komponen dibungkus di dalam konteks sehingga mereka dapat mengakses nilainya.

const App = ()=>{
  return(
    <div>
      <IDBContextProvider>
        <IDBUpdateComponent />
        <IDBConsumerComponent />
      </IDBContextProvider>
    </div>
  )
}
1
Murli Prajapati 10 Juli 2020, 09:38