Any atom must have a default
value when initializing it, this value can be any type, it can be a string, number, boolean, object
, array
, however, when the default value is an object or an array, the atom gets a special treatment.
Atom's value can be fetched in different ways, depends what are you trying to do.
For example, if you're using the atom outside a React component
or you're using it inside a component but don't want to rerender the component when the atom's value changes, you can use the atom.value
property.
// anywhere in your app
import { currencyAtom } from "~/src/atoms";
console.log(currencyAtom.value); // get current value
Another way to get the atom's value when you're inside a React component, we can use atom.useValue()
to get the atom's value and also trigger a component rerender when the atom's value changes.
import React from "react";
import { currencyAtom } from "~/src/atoms";
export default function Header() {
const currency = currencyAtom.useValue();
return (
<>
<h1>Header</h1>
Currency: {currency}
</>
);
}
The basic way to update atom's value is by using atom.update
, this method receives the new value of the atom and updates it.
// anywhere in your app
import { currencyAtom } from "~/src/atoms";
currencyAtom.update("USD"); // any component using the atom will be rerendered automatically.
We can also pass a callback to the update function, the callback will receive the old value and the atom instance.
// anywhere in your app
import { currencyAtom } from "~/src/atoms";
currencyAtom.update((oldValue, atom) => {
// do something with the old value
return "USD";
});
Please do remember that atom.update must receive a new reference of the value, otherwise it will not trigger the change event, for example atom.update({ ...user }) will trigger the change event.
// /src/atoms/user-atom.ts
import { atom } from "@mongez/react-atom";
export type UserData = {
name: string;
email: string;
age: number;
id: number;
};
export const userAtom = atom<UserData>({
key: "user",
default: {
name: "Hasan",
age: 30,
email: "hassanzohdy@gmail.com",
id: 1,
},
});
Now if we want to make an update for the user atom using atom.update
, it will be something like this:
// anywhere in your app
import { userAtom } from "~/src/atoms/user-atom";
userAtom.update({
...userAtom.value,
name: "Ahmed",
});
Or using callback to get the old value:
// anywhere in your app
import { userAtom } from "~/src/atoms/user-atom";
userAtom.update((oldValue) => {
return {
...oldValue,
name: "Ahmed",
};
});
Works exactly like update
method, but it will not trigger the change event.
// anywhere in your app
import { currencyAtom } from "~/src/atoms";
currencyAtom.silentUpdate("USD"); // any component using the atom will be rerendered automatically.
If the atom is an object atom, you can use atom.merge
to merge the new value with the old value.
// src/atoms/user-atom.ts
import { atom } from "@mongez/react-atom";
export type UserData = {
name: string;
email: string;
age: number;
id: number;
};
export const userAtom = atom<UserData>({
key: "user",
default: {
name: "Hasan",
age: 30,
email: "hassanzohdy@gmail.com",
id: 1,
},
});
Now if we want to make an update for the user atom using atom.update
, it will be something like this:
// anywhere in your app
import { userAtom } from "~/src/atoms";
userAtom.update({
...userAtom.value,
name: "Ahmed",
age: 25,
});
If you notice, we've to spread the old value and then add the new values, this is good, but we can use atom.merge
instead.
// anywhere in your app
import { userAtom } from "~/src/atoms";
userAtom.merge({
name: "Ahmed",
age: 25,
});
This is just a shortcut for atom.update
, it will merge the new value with the old value and then update the atom.
If you want to get the atom's value and update it at the same time, you can use atom.useState().
import React from "react";
import { currencyAtom } from "~/src/atoms";
export default function Header() {
const [currency, setCurrency] = currencyAtom.useState();
return (
<>
<h1>Header</h1>
Currency: {currency}
<button onClick={(e) => setCurrency("EUR")}>EUR</button>
<button onClick={(e) => setCurrency("USD")}>USD</button>
<button onClick={(e) => setCurrency("EGP")}>EGP</button>
</>
);
}
Works exactly like useState
hook, the first item in the returned array is the current value of the atom, the second item is a state updater for the atom's value.
The main difference here is when the atom's value is changed from any other place, this component will be rerendered automatically.
Wait for more, to be continued !