Mongez React Atom Part-3

Mohamed Eltahawy
Nov 22, 2023
2 min read
post_comment0 Comments
post_like0 Likes

#Watch form object's key changes

Another super amazing feature here is to watch for a property of theatom's valueif it's defined as an object.

1import React from "react";
2import { atom, Atom } from "@mongez/react-atom";
3
4type User = {
5  name: string;
6  email: string;
7  age: number;
8};
9
10const userAtom = atom<User>({
11  key: "user",
12  default: {},
13});
14

Now let's create a component to display the user's name and email.

1import React from "react";
2import { userAtom } from "~/src/atoms";
3
4export default function User() {
5  const user = userAtom.useValue();
6
7  return (
8    <>
9      <h1>User</h1>
10      <p>Name: {user.name}</p>
11      <p>Email: {user.email}</p>
12    </>
13  );
14}
15

Now let's update the user's name from another component.

1import React from "react";
2import { userAtom } from "~/src/atoms";
3
4export default function UserForm() {
5  const [user, setUser] = userAtom.useState();
6
7  return (
8    <>
9      <h1>User Form</h1>
10      <input
11        type="text"
12        value={user.name}
13        onChange={(e) => setUser({ ...user, name: e.target.value })}
14      />
15      <input
16        type="text"
17        value={user.email}
18        onChange={(e) => setUser({ ...user, email: e.target.value })}
19      />
20    </>
21  );
22}
23

This is great, but what if we want to have a component that will be rerendered only when the user's name changes, not the email, here we can useatom.useWatcherto watch for a specific property of the atom's value.

1import React from "react";
2import { userAtom } from "~/src/atoms";
3
4export default function User() {
5  const name = userAtom.useWatcher("name");
6
7  return (
8    <>
9      <h1>User</h1>
10      <p>Name: {name}</p>
11    </>
12  );
13}
14

Now when thenameproperty is changed, this component will be rerendered automatically, otherwise it won't.

#On Atom Reset

To listen to atom when it is reset, useonResetmethod.

1// anywhere in your app
2import { currencyAtom } from "~/src/atoms";
3
4currencyAtom.onReset((atom) => {
5  //
6});
7

This will be triggered after the update event is triggered

Using atom.use will merge bothuseValueanduseWatchermethods into one.

If theusereceived a parameter, then it will be watching for the given property change, otherwise it will watch for the entire atom's value change.

Starting from version 2 and above, atom.use will be the recommended way to watch for atom's value changes for single property atoms instead of useWatcher as useWatcher will be removed in the next release.

1type User = {
2  name: string;
3  age: number;
4  position: "developer" | "designer" | "manager";
5  notifications: number;
6};
7
8const userAtom = atom<User>({
9  key: "user",
10  default: {
11    name: "Hasan",
12    age: 25,
13    position: "developer",
14  },
15});
16
17// now in any component
18import userAtom from "./userAtom";
19export function Header() {
20  const notifications = userAtom.use("notifications");
21
22  return <header>{notifications}</header>;
23}
24

This will only re-render the component when thenotificationsproperty changes.

Usingusewithout any parameter will watch for the entire atom's value change.

1type User = {
2  name: string;
3  age: number;
4  position: "developer" | "designer" | "manager";
5  notifications: number;
6};
7
8// now in any component
9import userAtom from "./userAtom";
10
11export function Header() {
12  const user = userAtom.useValue();
13
14  return <header>{user.notifications}</header>;
15}
16

This will be rerendered when the entire atom's value changes.

1type User = {
2  name: string;
3  age: number;
4  position: "developer" | "designer" | "manager";
5  notifications: number;
6};
7
8// now in any component
9import userAtom from "./userAtom";
10
11export function Header() {
12  const notifications = userAtom.use("notifications"); // will return number, and Typescript will complain if you try to use other properties
13
14  return <header>{notifications}</header>;
15}
16

#Changing only single key in the atom's value

Instead of passing the whole object to thesetUserfunction, we can pass only the key we want to change usingatom.changefunction.

1import React from "react";
2import { userAtom } from "~/src/atoms";
3
4export default function UserForm() {
5  const [user, setUser] = userAtom.useState();
6
7  return (
8    <>
9      <h1>User Form</h1>
10      <input
11        type="text"
12        value={user.name}
13        onChange={(e) => userAtom.change("name", e.target.value)}
14      />
15      <input
16        type="text"
17        value={user.email}
18        onChange={(e) => userAtom.change("email", e.target.value)}
19      />
20    </>
21  );
22}
23

This will change only the given key in the atom's value, and trigger a component rerender if the atom's value is used in the component.

Please note thatchangemethod callsupdatemethod under the hood, so it will generate a new object.

Wait for more, to be continued !

You are not logged in.