Skip to content

Instantly share code, notes, and snippets.

@imneonizer
Last active February 19, 2025 15:27
Show Gist options
  • Save imneonizer/821077b948d79b24f510d78d2414c5f1 to your computer and use it in GitHub Desktop.
Save imneonizer/821077b948d79b24f510d78d2414c5f1 to your computer and use it in GitHub Desktop.
Automatic State Management in Next JS / React JS without any predefined schema.
// YT Tutorial: https://youtu.be/im3rWaN_2Qo
import { useReducer } from "react";
const readObject = (obj, path) => {
let val = null;
if (path.includes(".")) {
path
.split(".")
.map((path) => (val = val ? val[path] || null : obj[path] || null));
return val;
} else {
return obj[path];
}
};
const writeObject = (obj, path, val) => {
const keys = path.split(".");
const lastKey = keys.pop();
const lastObj = keys.reduce((obj, key) => (obj[key] = obj[key] || {}), obj);
lastObj[lastKey] = val;
return obj;
};
function reactState(defaultState) {
const [value, setValue] = useReducer(
(state, updates) =>
updates.__reset__
? {}
: {
...state,
...updates,
},
defaultState || {}
);
const reset = () => {
setValue({ __reset__: true });
};
const get = (key) => {
if (key) {
return readObject(value, key);
} else {
return value;
}
};
const set = (key, val) => {
if (typeof key === "string") {
setValue(writeObject(value, key, val));
} else {
setValue(key);
}
};
return { value, setValue, get, set, reset };
}
export default function StateManagement() {
const state = reactState({});
useEffect(() => {
console.log("lat or lng has changed");
}, [state.get("address.location")]);
useEffect(() => {
console.log("name has changed");
}, [state.get("name")]);
return (
<div className="m-4 text-2xl">
<p>Name: {state.get("name")}</p>
<p>Phone: {state.get("phone")}</p>
<div className="w-full border-b border-dashed my-2" />
{/* <pre>{JSON.stringify(state.get(""), null, 2)}</pre> */}
<pre>{JSON.stringify(state.get("address"), null, 2)}</pre>
<pre>{JSON.stringify(state.get("counter"), null, 2)}</pre>
<div className="mt-2 flex flex-col space-y-2">
<button
onClick={() => {
// setName("Nitin + " + Math.random().toString(36).substring(2, 8));
state.set(
"name",
"Nitin + " + Math.random().toString(36).substring(2, 8)
);
}}
className="bg-blue-700 rounded-md p-2 text-white active:opacity-80"
>
Update Name
</button>
<button
onClick={() => {
// setPhone(
// Math.floor(1000000000 + Math.random() * 9000000000).toString()
// );
state.set(
"phone",
Math.floor(1000000000 + Math.random() * 9000000000).toString()
);
}}
className="bg-blue-700 rounded-md p-2 text-white active:opacity-80"
>
Update Phone
</button>
<button
onClick={() => {
// setAddress((prev) => ({ ...prev, city: "Delhi" }));
state.set("address.city", "Delhi");
// state.set("address.location.lat", 23);
// state.set("address.location.lng", 24);
state.set("address.location", {
lat: Math.random() * 100,
lng: Math.random() * 100,
});
}}
className="bg-blue-700 rounded-md p-2 text-white active:opacity-80"
>
Update City
</button>
<button
onClick={() => {
state.set("address.pincode", 110045);
}}
className="bg-blue-700 rounded-md p-2 text-white active:opacity-80"
>
Update Pincode
</button>
<button
onClick={() => {
state.set(
"counter.firstLevel.secondLevel.thirdLevel.nLevel.increment",
(prev) => (prev || 0) + 1
);
}}
className="bg-blue-700 rounded-md p-2 text-white active:opacity-80"
>
Increment
</button>
</div>
</div>
);
}
@imneonizer
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment