-
Notifications
You must be signed in to change notification settings - Fork 54
feat: draft zustand state management system #280
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2d8cb57
46b79fc
03a5689
89804b5
2398139
aa6d5df
cad1567
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,10 +1,15 @@ | ||||||||||||||||||||||||
import { useEffect, useState } from "react"; | ||||||||||||||||||||||||
import { useEffect } from "react"; | ||||||||||||||||||||||||
import "./App.css"; | ||||||||||||||||||||||||
import { ParsedEntity, SDK } from "@dojoengine/sdk"; | ||||||||||||||||||||||||
import { SDK, createDojoStore } from "@dojoengine/sdk"; | ||||||||||||||||||||||||
import { Schema } from "./bindings.ts"; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
import { v4 as uuidv4 } from "uuid"; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
export const useDojoStore = createDojoStore<Schema>(); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
function App({ db }: { db: SDK<Schema> }) { | ||||||||||||||||||||||||
const [entities, setEntities] = useState<ParsedEntity<Schema>[]>([]); | ||||||||||||||||||||||||
const state = useDojoStore((state) => state); | ||||||||||||||||||||||||
const entities = useDojoStore((state) => state.entities); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||
let unsubscribe: (() => void) | undefined; | ||||||||||||||||||||||||
|
@@ -28,15 +33,7 @@ function App({ db }: { db: SDK<Schema> }) { | |||||||||||||||||||||||
response.data && | ||||||||||||||||||||||||
response.data[0].entityId !== "0x0" | ||||||||||||||||||||||||
) { | ||||||||||||||||||||||||
console.log(response.data); | ||||||||||||||||||||||||
setEntities((prevEntities) => { | ||||||||||||||||||||||||
return prevEntities.map((entity) => { | ||||||||||||||||||||||||
const newEntity = response.data?.find( | ||||||||||||||||||||||||
(e) => e.entityId === entity.entityId | ||||||||||||||||||||||||
); | ||||||||||||||||||||||||
return newEntity ? newEntity : entity; | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
state.setEntities(response.data); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}, | ||||||||||||||||||||||||
{ logging: true } | ||||||||||||||||||||||||
|
@@ -54,8 +51,6 @@ function App({ db }: { db: SDK<Schema> }) { | |||||||||||||||||||||||
}; | ||||||||||||||||||||||||
}, [db]); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
console.log("entities:"); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||
const fetchEntities = async () => { | ||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
|
@@ -76,23 +71,7 @@ function App({ db }: { db: SDK<Schema> }) { | |||||||||||||||||||||||
return; | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
if (resp.data) { | ||||||||||||||||||||||||
console.log(resp.data); | ||||||||||||||||||||||||
setEntities((prevEntities) => { | ||||||||||||||||||||||||
const updatedEntities = [...prevEntities]; | ||||||||||||||||||||||||
resp.data?.forEach((newEntity) => { | ||||||||||||||||||||||||
const index = updatedEntities.findIndex( | ||||||||||||||||||||||||
(entity) => | ||||||||||||||||||||||||
entity.entityId === | ||||||||||||||||||||||||
newEntity.entityId | ||||||||||||||||||||||||
); | ||||||||||||||||||||||||
if (index !== -1) { | ||||||||||||||||||||||||
updatedEntities[index] = newEntity; | ||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||
updatedEntities.push(newEntity); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
return updatedEntities; | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
state.setEntities(resp.data); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
); | ||||||||||||||||||||||||
|
@@ -104,20 +83,55 @@ function App({ db }: { db: SDK<Schema> }) { | |||||||||||||||||||||||
fetchEntities(); | ||||||||||||||||||||||||
}, [db]); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
const optimisticUpdate = async () => { | ||||||||||||||||||||||||
const entityId = | ||||||||||||||||||||||||
"0x571368d35c8fe136adf81eecf96a72859c43de7efd8fdd3d6f0d17e308df984"; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
Comment on lines
+87
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid hardcoding the Hardcoding the |
||||||||||||||||||||||||
const transactionId = uuidv4(); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
state.applyOptimisticUpdate(transactionId, (draft) => { | ||||||||||||||||||||||||
draft.entities[entityId].models.dojo_starter.Moves!.remaining = 10; | ||||||||||||||||||||||||
}); | ||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure entity exists before applying optimistic update When applying the optimistic update, ensure that Suggested fix: state.applyOptimisticUpdate(transactionId, (draft) => {
+ if (draft.entities[entityId]) {
draft.entities[entityId].models.dojo_starter.Moves!.remaining = 10;
+ }
}); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
try { | ||||||||||||||||||||||||
// Wait for the entity to be updated before full resolving the transaction. Reverts if the condition is not met. | ||||||||||||||||||||||||
const updatedEntity = await state.waitForEntityChange( | ||||||||||||||||||||||||
entityId, | ||||||||||||||||||||||||
(entity) => { | ||||||||||||||||||||||||
// Define your specific condition here | ||||||||||||||||||||||||
return entity?.models.dojo_starter.Moves?.can_move === true; | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
Comment on lines
+101
to
+102
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Define the specific condition for The condition in Example: return entity?.models.dojo_starter.Moves?.can_move === true;
- // Define your specific condition here
+ // Condition: Checks if the 'can_move' flag is true
|
||||||||||||||||||||||||
); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
console.log("Entity has been updated to active:", updatedEntity); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
console.log("Updating entities..."); | ||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||
console.error("Error updating entities:", error); | ||||||||||||||||||||||||
state.revertOptimisticUpdate(transactionId); | ||||||||||||||||||||||||
} finally { | ||||||||||||||||||||||||
console.log("Updating entities..."); | ||||||||||||||||||||||||
state.confirmTransaction(transactionId); | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
}; | ||||||||||||||||||||||||
Comment on lines
+112
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Review transaction confirmation placement Calling Suggested change: } catch (error) {
console.error("Error updating entities:", error);
state.revertOptimisticUpdate(transactionId);
- } finally {
+ } finally {
console.log("Updating entities...");
- state.confirmTransaction(transactionId);
}
+ state.confirmTransaction(transactionId); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||
|
||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||
<div> | ||||||||||||||||||||||||
<h1>Game State</h1> | ||||||||||||||||||||||||
{entities.map((entity) => ( | ||||||||||||||||||||||||
<div key={entity.entityId}> | ||||||||||||||||||||||||
<h2>Entity {entity.entityId}</h2> | ||||||||||||||||||||||||
<button onClick={optimisticUpdate}>update</button> | ||||||||||||||||||||||||
{Object.entries(entities).map(([entityId, entity]) => ( | ||||||||||||||||||||||||
<div key={entityId}> | ||||||||||||||||||||||||
<h2>Entity {entityId}</h2> | ||||||||||||||||||||||||
<h3>Position</h3> | ||||||||||||||||||||||||
<p> | ||||||||||||||||||||||||
Player:{" "} | ||||||||||||||||||||||||
{entity.models.dojo_starter.Position?.player ?? "N/A"} | ||||||||||||||||||||||||
<br /> | ||||||||||||||||||||||||
X: {entity.models.dojo_starter.Position?.vec.x ?? "N/A"} | ||||||||||||||||||||||||
X:{" "} | ||||||||||||||||||||||||
{entity.models.dojo_starter.Position?.vec?.x ?? "N/A"} | ||||||||||||||||||||||||
<br /> | ||||||||||||||||||||||||
Y: {entity.models.dojo_starter.Position?.vec.y ?? "N/A"} | ||||||||||||||||||||||||
Y:{" "} | ||||||||||||||||||||||||
{entity.models.dojo_starter.Position?.vec?.y ?? "N/A"} | ||||||||||||||||||||||||
</p> | ||||||||||||||||||||||||
<h3>Moves</h3> | ||||||||||||||||||||||||
<p> | ||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider optimizing state selection
While using
useDojoStore
for state management is a good approach, selecting the entire state on line 11 might lead to unnecessary re-renders. Consider selecting only the specific parts of the state that this component needs.Example:
This way, the component will only re-render when these specific parts of the state change.