Jotai có khả năng mở rộng từ việc thay thế useState đơn giản đến các ứng dụng TypeScript doanh nghiệp.
- API cốt lõi tối giản (2kb)
- Nhiều tiện ích và tích hợp
- Không sử dụng chuỗi làm khóa (so với Recoil)
Đầu tiên, tạo một nguyên thủy atom
Một atom đại diện cho một phần trạng thái. Bạn chỉ cần xác định một giá trị ban đầu, có thể là các giá trị nguyên thủy như chuỗi và số, đối tượng và mảng. Bạn có thể tạo nhiều atom nguyên thủy tùy thích.
import { atom } from ‘jotai’ const countAtom = atom(0) const countryAtom = atom(‘Nhật Bản’) const citiesAtom = atom([‘Tokyo’, ‘Kyoto’, ‘Osaka’]) const mangaAtom = atom({ ‘Dragon Ball’: 1984, ‘One Piece’: 1997, Naruto: 1999 })
Sử dụng atom trong các thành phần của bạn
Nó có thể được sử dụng giống như React.useState
:
import { useAtom } from ‘jotai’ function Counter() { const [count, setCount] = useAtom(countAtom) return (
{count} …
Tạo các atom phụ thuộc với các giá trị tính toán
Một atom chỉ đọc mới có thể được tạo ra từ các atom hiện có bằng cách truyền một hàm đọc làm đối số đầu tiên. get
cho phép bạn truy xuất giá trị ngữ cảnh của bất kỳ atom nào.
const doubledCountAtom = atom((get) => get(countAtom) * 2) function DoubleCounter() { const [doubledCount] = useAtom(doubledCountAtom) return
{doubledCount}
}
Tạo một atom từ nhiều atom
Bạn có thể kết hợp nhiều atom để tạo ra một atom tạo điều kiện.
const count1 = atom(1) const count2 = atom(2) const count3 = atom(3) const sum = atom((get) => get(count1) + get(count2) + get(count3))
Hoặc nếu bạn thích mô hình lập trình hàm …
const atoms = [count1, count2, count3, …otherAtoms] const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
Các atoms bất đồng bộ dẫn xuất
Bạn có thể làm cho hàm đọc trở thành một hàm bất đồng bộ.
const urlAtom = atom(‘https://json.host.com’) const fetchUrlAtom = atom(async (get) => { const response = await fetch(get(urlAtom)) return await response.json() }) function Status() { // Khi urlAtom thay đổi và hàm bất đồng bộ ở trên kết thúc, nó sẽ kích hoạt việc vẽ lại thành phần const [json] = useAtom(fetchUrlAtom) …
Bạn có thể tạo một atom dẫn xuất có khả năng ghi
Chỉ định một hàm ghi tại đối số thứ hai. get
sẽ trả về giá trị hiện tại của một atom. set
sẽ cập nhật giá trị của một atom.
const decrementCountAtom = atom( (get) => get(countAtom), (get, set, _arg) => set(countAtom, get(countAtom) – 1) ) function Counter() { const [count, decrement] = useAtom(decrementCountAtom) return (
{count} …
Atoms dẫn xuất chỉ có khả năng ghi
Chỉ cần không định nghĩa một hàm đọc.
const multiplyCountAtom = atom(null, (get, set, by) => set(countAtom, get(countAtom) * by) ) function Controls() { const [, multiply] = useAtom(multiplyCountAtom) return }
Hành động bất đồng bộ
Chỉ cần làm cho hàm ghi trở thành một hàm bất đồng bộ và gọi set
khi bạn đã sẵn sàng.
const fetchCountAtom = atom( (get) => get(countAtom), async (_get, set, url) => { const response = await fetch(url) set(countAtom, (await response.json()).count) } ) function Controls() { const [count, compute] = useAtom(fetchCountAtom) return ( …
Liên kết
.eslintrc.json
{
"env": {
"browser": true,
"shared-node-browser": true,
"node": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended",
"plugin:react-hooks/recommended",
"plugin:import/errors",
"plugin:import/warnings"
],
"plugins": [
"@typescript-eslint",
"react",
"prettier",
"react-hooks",
"import",
"vitest"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"rules": {
"eqeqeq": "error",
"no-var": "error",
"prefer-const": "error",
"curly": ["warn", "multi-line", "consistent"],
"no-console": "off",
"import/extensions": ["error", "always"],
"import/no-unresolved": ["error", { "commonjs": true, "amd": true }],
"import/export": "error",
"@typescript-eslint/no-duplicate-imports": ["error"],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
],
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"vitest/consistent-test-it": [
"error",
{ "fn": "it", "withinDescribe": "it" }
],
"import/namespace": "off",
"import/named": "off",
"import/order": [
"error",
{
"alphabetize": { "order": "asc", "caseInsensitive": true },
"groups": [
"builtin",
"external",
"internal",
"parent",
"sibling",
"index",
"object"
],
"newlines-between": "never",
"pathGroups": [
{
"pattern": "react",
"group": "builtin",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["builtin"]
}
],
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off",
"sort-imports": [
"error",
{
"ignoreDeclarationSort": true
}
]
},
"settings": {
"react": {
"version": "detect"
},
"import/extensions": [".js", ".jsx", ".ts", ".tsx"],
"import/parsers": {
"@typescript-eslint/parser": [".js", ".jsx", ".ts", ".tsx"]
},
"import/resolver": {
"alias": {
"extensions": [".js", ".jsx", ".ts", ".tsx"],
"map": [
["^jotai$", "./src/index.ts"],
["jotai", "./src"]
]
}
}
},
"overrides": [
{
"files": ["tests/**/*.ts", "tests/**/*.tsx"],
"rules": {
"import/extensions": ["error", "never"]
}
},
{
"files": ["./*.js"],
"rules": {
"@typescript-eslint/no-var-requires": "off"
}
}
]
}
.gitignore
# dependencies
node_modules
.pnp
.pnp.js
# testing
coverage
# development
.devcontainer
.vscode
# production
dist
build
# dotenv environment variables file
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# misc
.DS_Store
.idea
Chi tiết tải về:
Tác giả: pmndrs
Nguồn: https://github.com/pmndrs/jotai
Giấy phép: MIT license