Global State Management #145
Replies: 6 comments 4 replies
-
tracking ticket for this already exists at #18, but we can continue conversation here for multithreaded discussion |
Beta Was this translation helpful? Give feedback.
-
simplest example that comes to mind: a top level component represents a dapp, it may have a user preferences tab which affects some things about the application. Those preferences should not need to be passed as props through the entire component tree |
Beta Was this translation helpful? Give feedback.
-
potential solution: components can initialize a store keyed by a string e.g. "mydapp-preferences", other components must know the key of the data store they wish to interact with whether the store actually lives in the initializing component or the OWA is an implementation detail hurdle: most stores now work on a hooks interface. Could we support cross-component hooks? |
Beta Was this translation helpful? Give feedback.
-
What you're describing is well-suited for the current architecture. I think the big challenge for supporting existing off-the-shelf solutions is the iframe barrier between containers; e.g. we couldn't pass That said, anything we pass as A naive solution could be something like: // in container boilerplate
function useBWEStore() { ... }
// component code
const { getState, setState } = useBWEStore();
const [favoriteDapps, setFavoriteDapps] = useState([]);
useEffect(() => {
setFavoriteDapps(await getState("dapp.favorites"));
}, []);
useEffect(() => {
await setState("dapp.preferences", (preferences) => [...preferences, preference]);
}, [preference]); |
Beta Was this translation helpful? Give feedback.
-
Global stores would make handling optimistic updates and subscription updates a lot easier: posts & comments could use it at the moment. |
Beta Was this translation helpful? Give feedback.
-
This makes me think what we ultimately want is a query layer for common operations. The cache we're discussing here would be the first step, but it doesn't address potential race conditions when multiple components are fetching the same data, say on initialization: const fetchPost = (postId) => SocialDB.get({ keys: [`test.near/posts/${postId}`] });
// if multiple components run this for the same post on render, the fetches are duplicated
if (!(await getState(postId))) {
post = await fetchPost(postId);
setState(`posts/${postId}`, post);
} By querying a common layer that initially supports SocialDB, Near RPC, etc., we could abstract the cache behind a query layer that runs in the shared context. Basically just a web worker in the outer application supporting an interface for fetching BOS data, caching the arguments and pushing responses to subscribed components. Now the above example becomes something like: const post = await BOSQuery.SocialDB.getAndCache({ id: postId, path: 'test.near/posts/' }) |
Beta Was this translation helpful? Give feedback.
-
A pretty common need for larger applications is implementing some type of global state and/or data fetching management. Tools like Zustand and React Query are commonly used in modern React applications to implement these patterns.
The current VM doesn't support any type of global state management - which leaves you with the only option of passing props. Passing props works well at a certain scale, but it can start to become unwieldy when you have multiple levels of components that all need to forward along the same props. Then it becomes even more challenging when a deeply nested component needs to modify that state.
Ideally, the new web engine would support usage of standard tools (like the ones mentioned above) across components. I know this will probably introduce a new set of security challenges, but it would be great to start thinking through how we could achieve this goal.
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions