初步解析
下面是 useStore 在 React 中的实现
import { listenKeys } from 'nanostores';
import { useCallback, useSyncExternalStore } from 'react';
export function useStore(store, opts = {}) {
let subscribe = useCallback((onChange) => (opts.keys ? listenKeys(store, opts.keys, onChange) : store.listen(onChange)), [opts.keys, store]);
let get = store.get.bind(store);
return useSyncExternalStore(subscribe, get, get);
}
[useSyncExternalStore]](https://react.dev/reference/react/useSyncExternalStore#usesyncexternalstore)
const snapshot = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot?)
Call useSyncExternalStore at the top level of your component to read a value from an external data store.
import { useSyncExternalStore } from 'react';
import { todosStore } from './todoStore.js';
function TodosApp() {
const todos = useSyncExternalStore(todosStore.subscribe, todosStore.getSnapshot);
// ...
}
It returns the snapshot of the data in the store. You need to pass two functions as arguments:
The subscribe function should subscribe to the store and return a function that unsubscribes. The getSnapshot function should read a snapshot of the data from the store.
// This is an example of a third-party store
// that you might need to integrate with React.
// If your app is fully built with React,
// we recommend using React state instead.
let nextId = 0;
let todos = [{ id: nextId++, text: 'Todo #1' }];
let listeners = [];
export const todosStore = {
addTodo() {
todos = [...todos, { id: nextId++, text: 'Todo #' + nextId }];
emitChange();
},
subscribe(listener) {
listeners = [...listeners, listener];
return () => {
listeners = listeners.filter((l) => l !== listener);
};
},
getSnapshot() {
return todos;
},
};
function emitChange() {
for (let listener of listeners) {
listener();
}
}
import { useSyncExternalStore } from 'react';
import { todosStore } from './todoStore.js';
export default function TodosApp() {
const todos = useSyncExternalStore(todosStore.subscribe, todosStore.getSnapshot);
return (
<>
<button onClick={() => todosStore.addTodo()}>Add todo</button>
<hr />
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</>
);
}