Remove any recoil reference from project (#18250)
## Remove all Recoil references and replace with Jotai ### Summary - Removed every occurrence of Recoil from the entire codebase, replacing with Jotai equivalents where applicable - Updated `README.md` tech stack: `Recoil` → `Jotai` - Rewrote documentation code examples to use `createAtomState`/`useAtomState` instead of `atom`/`useRecoilState`, and removed `RecoilRoot` wrappers - Cleaned up source code comment and Cursor rules that referenced Recoil - Applied changes across all 13 locale translations (ar, cs, de, es, fr, it, ja, ko, pt, ro, ru, tr, zh)
This commit is contained in:
@@ -36,18 +36,18 @@ export const userByIdState = createAtomFamilyState<User | null, string>({
|
||||
|
||||
## Jotai Hooks
|
||||
```typescript
|
||||
// useAtomState - read and write (like useRecoilState)
|
||||
// useAtomState - read and write
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
// useAtomStateValue - read only (like useRecoilValue)
|
||||
// useAtomStateValue - read only
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
|
||||
// useSetAtomState - write only (like useSetRecoilState)
|
||||
// useSetAtomState - write only
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
```
|
||||
|
||||
## Provider
|
||||
Jotai works without a Provider by default (unlike Recoil's RecoilRoot). For scoped stores or testing, use `Provider` from `jotai`.
|
||||
Jotai works without a Provider by default. For scoped stores or testing, use `Provider` from `jotai`.
|
||||
|
||||
## Local State Guidelines
|
||||
```typescript
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
needs: changed-files-check
|
||||
if: needs.changed-files-check.outputs.any_changed == 'true'
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
task: [lint, typecheck, test, validate]
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
ci-zapier-status-check:
|
||||
if: always() && !cancelled()
|
||||
timeout-minutes: 5
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: depot-ubuntu-24.04
|
||||
needs: [changed-files-check, zapier-test]
|
||||
steps:
|
||||
- name: Fail job if any needs failed
|
||||
|
||||
@@ -109,7 +109,7 @@ Below are a few features we have implemented to date:
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
- [Nx](https://nx.dev/)
|
||||
- [NestJS](https://nestjs.com/), with [BullMQ](https://bullmq.io/), [PostgreSQL](https://www.postgresql.org/), [Redis](https://redis.io/)
|
||||
- [React](https://reactjs.org/), with [Recoil](https://recoiljs.org/), [Emotion](https://emotion.sh/) and [Lingui](https://lingui.dev/)
|
||||
- [React](https://reactjs.org/), with [Jotai](https://jotai.org/), [Emotion](https://emotion.sh/) and [Lingui](https://lingui.dev/)
|
||||
|
||||
|
||||
|
||||
|
||||
+19
-18
@@ -7,9 +7,9 @@ This document outlines the best practices you should follow when working on the
|
||||
|
||||
## State management
|
||||
|
||||
React and Recoil handle state management in the codebase.
|
||||
React and Jotai handle state management in the codebase.
|
||||
|
||||
### Use `useRecoilState` to store state
|
||||
### Use Jotai atoms to store state
|
||||
|
||||
It's good practice to create as many atoms as you need to store your state.
|
||||
|
||||
@@ -20,13 +20,16 @@ It's better to use extra atoms than trying to be too concise with props drilling
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -43,7 +46,7 @@ export const MyComponent = () => {
|
||||
|
||||
Avoid using `useRef` to store state.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or Jotai atoms with `useAtomState`.
|
||||
|
||||
See [how to manage re-renders](#managing-re-renders) if you feel like you need `useRef` to prevent some re-renders from happening.
|
||||
|
||||
@@ -83,8 +86,8 @@ You can apply the same for data fetching logic, with Apollo hooks.
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
// because useEffect needs to be re-evaluated
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -96,9 +99,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -106,14 +107,14 @@ export const App = () => (
|
||||
// ✅ Good, will not cause re-renders if data is not changing,
|
||||
// because useEffect is re-evaluated in another sibling component
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -125,16 +126,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Use recoil family states and recoil family selectors
|
||||
### Use atom family states and selectors
|
||||
|
||||
Recoil family states and selectors are a great way to avoid re-renders.
|
||||
Atom family states and selectors are a great way to avoid re-renders.
|
||||
|
||||
They are useful when you need to store a list of items.
|
||||
|
||||
|
||||
+2
-2
@@ -83,9 +83,9 @@ See [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) for more de
|
||||
|
||||
### States
|
||||
|
||||
Contains the state management logic. [RecoilJS](https://recoiljs.org) handles this.
|
||||
Contains the state management logic. [Jotai](https://jotai.org) handles this.
|
||||
|
||||
- Selectors: See [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) for more details.
|
||||
- Selectors: Derived atoms (using `createAtomSelector`) compute values from other atoms and are automatically memoized.
|
||||
|
||||
React's built-in state management still handles state within a component.
|
||||
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ The project has a clean and simple stack, with minimal boilerplate code.
|
||||
- [React](https://react.dev/)
|
||||
- [Apollo](https://www.apollographql.com/docs/)
|
||||
- [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
- [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
- [Jotai](https://jotai.org/)
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testing**
|
||||
@@ -76,7 +76,7 @@ To avoid unnecessary [re-renders](/developers/contribute/capabilities/frontend-d
|
||||
|
||||
### State Management
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) handles state management.
|
||||
[Jotai](https://jotai.org/) handles state management.
|
||||
|
||||
See [best practices](/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) for more information on state management.
|
||||
|
||||
|
||||
+3
-3
@@ -159,7 +159,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Internally, the currently selected scope is stored in a Recoil state that is shared across the application :
|
||||
Internally, the currently selected scope is stored in a Jotai atom that is shared across the application :
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -168,10 +168,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
But this Recoil state should never be handled manually ! We'll see how to use it in the next section.
|
||||
But this atom should never be handled manually ! We'll see how to use it in the next section.
|
||||
|
||||
## How is it working internally?
|
||||
|
||||
We made a thin wrapper on top of [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) that makes it more performant and avoids unnecessary re-renders.
|
||||
|
||||
We also create a Recoil state to handle the hotkey scope state and make it available everywhere in the application.
|
||||
We also create a Jotai atom to handle the hotkey scope state and make it available everywhere in the application.
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ title: أفضل الممارسات
|
||||
|
||||
## إدارة الحالة
|
||||
|
||||
تقوم React و Recoil بإدارة الحالة في قاعدة الشيفرة.
|
||||
تقوم React و Jotai بإدارة الحالة في قاعدة الشيفرة.
|
||||
|
||||
### استخدم `useRecoilState` لتخزين الحالة
|
||||
### استخدم `useAtomState` لتخزين الحالة
|
||||
|
||||
من الجيد إنشاء أكبر عدد ممكن من الذرات لتخزين الحالة الخاصة بك.
|
||||
|
||||
@@ -19,13 +19,16 @@ title: أفضل الممارسات
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
تجنب استخدام `useRef` لتخزين الحالة.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
انظر [كيفية إدارة إعادة العرض](#managing-re-renders) إذا شعرت أنك بحاجة إلى `useRef` لمنع بعض إعادة العرض من الحدوث.
|
||||
|
||||
@@ -82,8 +85,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
|
||||
// ❌ سيّئ، سيتسبب في إعادة التصيير حتى إذا لم تتغير البيانات،
|
||||
// لأن useEffect يحتاج إلى إعادة التقييم
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ جيّد، لن يتسبب في إعادة التصيير إذا لم تتغير البيانات،
|
||||
// لأن useEffect يُعاد تقييمه في مكوّن شقيق آخر
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### استخدم حالات عائلة Recoil ومحددات عائلة Recoil
|
||||
### استخدم حالات عائلة Jotai ومحددات عائلة Jotai
|
||||
|
||||
حالات عائلة Recoil والمحددات تعتبر طريقة رائعة لتجنب إعادة العرض.
|
||||
حالات عائلة Jotai والمحددات تعتبر طريقة رائعة لتجنب إعادة العرض.
|
||||
|
||||
إنها مفيدة عندما تحتاج إلى تخزين قائمة من العناصر.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ module1
|
||||
|
||||
### الحالات
|
||||
|
||||
تشمل منطق إدارة الحالة. [RecoilJS](https://recoiljs.org) يتولّى ذلك.
|
||||
تشمل منطق إدارة الحالة. [Jotai](https://jotai.org) يتولّى ذلك.
|
||||
|
||||
* المحددات: انظر [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) لمزيد من التفاصيل.
|
||||
* المحددات: الذرات المشتقة (باستخدام `createAtomSelector`) تحسب القيم من ذرات أخرى ويتم تخزينها تلقائيًا.
|
||||
|
||||
لا تزال إدارة الحالة المدمجة في React تتولّى الحالة داخل المكوّن.
|
||||
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ title: أوامر الواجهة الأمامية
|
||||
* "[React](https://react.dev/)"
|
||||
* "[Apollo](https://www.apollographql.com/docs/)"
|
||||
* "[GraphQL Codegen](https://the-guild.dev/graphql/codegen)"
|
||||
* "[Recoil](https://recoiljs.org/docs/introduction/core-concepts)"
|
||||
* "[Jotai](https://jotai.org/)"
|
||||
* "[TypeScript](https://www.typescriptlang.org/)"
|
||||
|
||||
**الاختبار**
|
||||
@@ -73,7 +73,7 @@ To avoid unnecessary [re-renders](/l/ar/developers/contribute/capabilities/front
|
||||
|
||||
### "إدارة الحالة"
|
||||
|
||||
"[Recoil](https://recoiljs.org/docs/introduction/core-concepts) يتعامل مع إدارة الحالة."
|
||||
"[Jotai](https://jotai.org/) يتعامل مع إدارة الحالة."
|
||||
|
||||
"راجع [أفضل الممارسات](/l/ar/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) لمزيد من المعلومات حول إدارة الحالة."
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
داخليًا، يتم تخزين النطاق المحدد حاليًا في حالة Recoil مشتركة عبر التطبيق:
|
||||
داخليًا، يتم تخزين النطاق المحدد حاليًا في حالة Jotai مشتركة عبر التطبيق:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
لكن لا يجب التعامل مع هذه الحالة Recoil يدويًا! سنرى كيف يمكن استخدامها في القسم التالي.
|
||||
لكن لا يجب التعامل مع هذه الحالة Jotai يدويًا! سنرى كيف يمكن استخدامها في القسم التالي.
|
||||
|
||||
## كيف يعمل داخليًا؟
|
||||
|
||||
قمنا بإنشاء غلاف رقيق فوق [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) والذي يجعله أكثر كفاءة ويتجنب عمليات إعادة التقديم غير الضرورية.
|
||||
|
||||
ونقوم أيضًا بإنشاء حالة Recoil للتعامل مع حالة نطاق المفتاح وجعلها متاحة في جميع أنحاء التطبيق.
|
||||
ونقوم أيضًا بإنشاء حالة Jotai للتعامل مع حالة نطاق المفتاح وجعلها متاحة في جميع أنحاء التطبيق.
|
||||
|
||||
@@ -14,7 +14,6 @@ image: /images/user-guide/github/github-header.png
|
||||
<Tab title="استخدام">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
<Tab title="استخدام">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tab title="27332A2E2F2745">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="اسم المستخدم"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
},{
|
||||
@@ -81,12 +78,10 @@ export const MyComponent = () => {
|
||||
<Tab title="الاستخدام">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("تم تشغيل الدالة onValidate")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="المهمة: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};},{
|
||||
```
|
||||
|
||||
+18
-17
@@ -6,9 +6,9 @@ Tento dokument popisuje osvědčené postupy, které byste měli dodržovat při
|
||||
|
||||
## Správa stavu
|
||||
|
||||
React a Recoil zajišťují správu stavu v kódu.
|
||||
React a Jotai zajišťují správu stavu v kódu.
|
||||
|
||||
### Použijte `useRecoilState` k ukládání stavu
|
||||
### Použijte `useAtomState` k ukládání stavu
|
||||
|
||||
Je dobrým zvykem vytvořit tolik atomů, kolik potřebujete ke správě stavu.
|
||||
|
||||
@@ -19,13 +19,16 @@ Je lepší použít více atomů než se snažit být příliš stručný s prop
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Vyhněte se používání `useRef` k ukládání stavu.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
Podívejte se, jak spravovat překreslení, pokud máte pocit, že potřebujete `useRef`, abyste zabránili některým překreslením.
|
||||
|
||||
@@ -82,8 +85,8 @@ Stejný postup můžete aplikovat na logiku získávání dat pomocí Apollo hoo
|
||||
// ❌ Špatně, způsobí překreslení i když se data nemění,
|
||||
// protože useEffect je třeba přehodnotit
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);},{
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Dobře, nezpůsobí překreslení, pokud se data nemění,
|
||||
// protože useEffect je přehodnoceno v další sourozené komponentě
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,14 +125,14 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Použijte Recoil family states a Recoil family selectors
|
||||
### Použijte atom family states a atom family selectors
|
||||
|
||||
Stavy rodiny třísek a selektory jsou skvělý způsob, jak se vyhnout překreslování.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Více podrobností naleznete v [Hooks](https://react.dev/learn/reusing-logic-wit
|
||||
|
||||
### Stavy
|
||||
|
||||
Obsahuje logiku správy stavů. To řeší [RecoilJS](https://recoiljs.org).
|
||||
Obsahuje logiku správy stavů. To řeší [Jotai](https://jotai.org).
|
||||
|
||||
* Selektory: Více podrobností naleznete v [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors).
|
||||
* Selektory: Odvozené atomy (pomocí `createAtomSelector`) počítají hodnoty z jiných atomů a jsou automaticky memoizovány.
|
||||
|
||||
Vestavěná správa stavů v Reactu stále spravuje stav uvnitř komponenty.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Projekt má čistý a jednoduchý stack s minimálním počtem šablonových kó
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testování**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/cs/developers/contribute/capabilities/front
|
||||
|
||||
### Správa stavu
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) zajišťuje správu stavu.
|
||||
[Jotai](https://jotai.org/) zajišťuje správu stavu.
|
||||
|
||||
Podívejte se na [osvědčené postupy](/l/cs/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pro více informací o správě stavu.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Interně je aktuálně vybraný rozsah uložen v Recoil stavu, který je sdílen napříč aplikací :
|
||||
Interně je aktuálně vybraný rozsah uložen v Jotai stavu, který je sdílen napříč aplikací :
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Ale tento Recoil stav by neměl být nikdy řízen ručně! Ukážeme si, jak jej používat v příští sekci.
|
||||
Ale tento Jotai stav by neměl být nikdy řízen ručně! Ukážeme si, jak jej používat v příští sekci.
|
||||
|
||||
## Jak to funguje interně?
|
||||
|
||||
Vytvořili jsme tenkou vrstvu nad [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), která je výkonnější a vyhýbá se zbytečným překreslením.
|
||||
|
||||
Také jsme vytvořili Recoil stav, abychom mohli řídit stav rozsahu klávesových zkratek a učinit jej dostupným kdekoli v aplikaci.
|
||||
Také jsme vytvořili Jotai stav, abychom mohli řídit stav rozsahu klávesových zkratek a učinit jej dostupným kdekoli v aplikaci.
|
||||
|
||||
@@ -14,7 +14,6 @@ Rozbalovací výběr ikon, který uživatelům umožňuje vybrat ikonu ze seznam
|
||||
<Tab title="Použití">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Umožňuje uživatelům vybrat hodnotu z nabídky předdefinovaných možností.
|
||||
<Tab title="Použití">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Umožňuje uživatelům zadávat a upravovat text.
|
||||
<Tab title="Použití">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ Textová vstupní komponenta, která automaticky přizpůsobuje svou výšku na
|
||||
<Tab title="Použití">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Dieses Dokument beschreibt die besten Praktiken, die Sie beim Arbeiten am Fronte
|
||||
|
||||
## Zustandsverwaltung
|
||||
|
||||
React und Recoil übernehmen die Zustandsverwaltung im Code.
|
||||
React und Jotai übernehmen die Zustandsverwaltung im Code.
|
||||
|
||||
### Verwenden Sie `useRecoilState`, um den Zustand zu speichern.
|
||||
### Verwenden Sie `useAtomState`, um den Zustand zu speichern.
|
||||
|
||||
Es ist eine gute Praxis, so viele Atome zu erstellen, wie Sie benötigen, um Ihren Zustand zu speichern.
|
||||
|
||||
@@ -19,13 +19,16 @@ Es ist besser, zusätzliche Atome zu verwenden, als zu versuchen, mit Prop Drill
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Vermeiden Sie die Verwendung von `useRef`, um den Zustand zu speichern.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
Sehen Sie sich [an, wie Re-Renderings verwaltet werden können](#managing-re-renders), falls Sie das Gefühl haben, dass Sie `useRef` benötigen, um einige Re-Renderings zu verhindern.
|
||||
|
||||
@@ -82,8 +85,8 @@ Dasselbe können Sie auch für die Datenabruflogik mit Apollo-Hooks anwenden.
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
// because useEffect needs to be re-evaluated
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Good, will not cause re-renders if data is not changing,
|
||||
// because useEffect is re-evaluated in another sibling component
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Verwenden Sie Recoil-Familienzustände und Recoil-Familienselektoren
|
||||
### Verwenden Sie Jotai-Familienzustände und Jotai-Familienselektoren
|
||||
|
||||
Recoil-Familienzustände und -Selektoren sind eine großartige Möglichkeit, Re-Renders zu vermeiden.
|
||||
Jotai-Familienzustände und -Selektoren sind eine großartige Möglichkeit, Re-Renders zu vermeiden.
|
||||
|
||||
Sie sind nützlich, wenn Sie eine Liste von Elementen speichern müssen.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Weitere Details finden Sie unter [Hooks](https://react.dev/learn/reusing-logic-w
|
||||
|
||||
### Zustände
|
||||
|
||||
Enthält die State-Management-Logik. [RecoilJS](https://recoiljs.org) übernimmt dies.
|
||||
Enthält die State-Management-Logik. [Jotai](https://jotai.org) übernimmt dies.
|
||||
|
||||
* Selektoren: Weitere Einzelheiten finden Sie unter [RecoilJS Selektoren](https://recoiljs.org/docs/basic-tutorial/selectors).
|
||||
* Selektoren: Abgeleitete Atome (mit `createAtomSelector`) berechnen Werte aus anderen Atomen und werden automatisch memoisiert.
|
||||
|
||||
Die integrierte Zustandsverwaltung von React verwaltet weiterhin den Zustand innerhalb einer Komponente.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Das Projekt hat einen sauberen und einfachen Stack mit minimalem Boilerplate-Cod
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Tests**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/de/developers/contribute/capabilities/front
|
||||
|
||||
### Zustandsverwaltung
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) übernimmt die Zustandsverwaltung.
|
||||
[Jotai](https://jotai.org/) übernimmt die Zustandsverwaltung.
|
||||
|
||||
Siehe [Best Practices](/l/de/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) für mehr Informationen zur Zustandsverwaltung.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Intern wird der aktuell ausgewählte Bereich in einem Recoil-State gespeichert, der in der gesamten Anwendung geteilt wird:
|
||||
Intern wird der aktuell ausgewählte Bereich in einem Jotai-State gespeichert, der in der gesamten Anwendung geteilt wird:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Aber dieser Recoil-State sollte niemals manuell bearbeitet werden! Wir werden im nächsten Abschnitt sehen, wie man es verwendet.
|
||||
Aber dieser Jotai-State sollte niemals manuell bearbeitet werden! Wir werden im nächsten Abschnitt sehen, wie man es verwendet.
|
||||
|
||||
## Wie funktioniert es intern?
|
||||
|
||||
Wir haben eine dünne Schicht über [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) erstellt, die es leistungsfähiger macht und unnötige Neu-Renderings vermeidet.
|
||||
|
||||
Wir haben auch einen Recoil-State erstellt, um den Tastenkombinationsbereich zu verwalten und in der gesamten Anwendung verfügbar zu machen.
|
||||
Wir haben auch einen Jotai-State erstellt, um den Tastenkombinationsbereich zu verwalten und in der gesamten Anwendung verfügbar zu machen.
|
||||
|
||||
@@ -14,7 +14,6 @@ Eine Dropdown-basierte Symbolauswahl, mit der Benutzer ein Symbol aus einer List
|
||||
<Tab title=""Verwendung"">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Ermöglicht es Benutzern, einen Wert aus einer Liste vordefinierter Optionen aus
|
||||
<Tab title=""Verwendung"">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Ermöglicht es den Benutzern, Text einzugeben und zu bearbeiten.
|
||||
<Tab title="Verwendung">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ Textkomponente, die ihre Höhe automatisch anhand des Inhalts anpasst.
|
||||
<Tab title="Verwendung">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Este documento describe las mejores prácticas que debes seguir al trabajar en e
|
||||
|
||||
## Gestión de estado
|
||||
|
||||
React y Recoil manejan la gestión de estado en la base de código.
|
||||
React y Jotai manejan la gestión de estado en la base de código.
|
||||
|
||||
### Usa `useRecoilState` para almacenar el estado
|
||||
### Usa `useAtomState` para almacenar el estado
|
||||
|
||||
Es buena práctica crear tantos átomos como necesites para almacenar tu estado.
|
||||
|
||||
@@ -17,13 +17,16 @@ Es buena práctica crear tantos átomos como necesites para almacenar tu estado.
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -40,7 +43,7 @@ export const MyComponent = () => {
|
||||
|
||||
Evita usar `useRef` para almacenar el estado.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
Consulta [cómo gestionar las re-renderizaciones](#managing-re-renders) si sientes que necesitas `useRef` para evitar algunas re-renderizaciones.
|
||||
|
||||
@@ -80,8 +83,8 @@ Puedes aplicar lo mismo para la lógica de obtención de datos, con hooks de Apo
|
||||
// ❌ Malo, provocará re-renderizados incluso si los datos no cambian,
|
||||
// porque useEffect necesita volver a evaluarse
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -93,9 +96,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -103,14 +104,14 @@ export const App = () => (
|
||||
// ✅ Bueno, no provocará re-renderizados si los datos no cambian,
|
||||
// porque useEffect se vuelve a evaluar en otro componente hermano
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -122,16 +123,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Usa estados de familia de recoil y selectores de familia de recoil
|
||||
### Usa estados de familia de jotai y selectores de familia de jotai
|
||||
|
||||
Los estados y selectores de familia de recoil son una gran manera de evitar re-renderizaciones.
|
||||
Los estados y selectores de familia de jotai son una gran manera de evitar re-renderizaciones.
|
||||
|
||||
Son útiles cuando necesitas almacenar una lista de elementos.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Ver [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) para más d
|
||||
|
||||
### Estados
|
||||
|
||||
Contiene la lógica de gestión de estado. [RecoilJS](https://recoiljs.org) maneja esto.
|
||||
Contiene la lógica de gestión de estado. [Jotai](https://jotai.org) maneja esto.
|
||||
|
||||
* Selectores: Ver [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) para más detalles.
|
||||
* Selectores: Los átomos derivados (usando `createAtomSelector`) calculan valores a partir de otros átomos y se memorizan automáticamente.
|
||||
|
||||
La gestión de estado incorporada de React todavía maneja el estado dentro de un componente.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ El proyecto tiene un stack limpio y sencillo, con un código boilerplate mínimo
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Pruebas**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/es/developers/contribute/capabilities/front
|
||||
|
||||
### Gestión del Estado
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) maneja la gestión del estado.
|
||||
[Jotai](https://jotai.org/) maneja la gestión del estado.
|
||||
|
||||
Ver [mejores prácticas](/l/es/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para más información sobre la gestión del estado.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Internamente, el ámbito seleccionado se almacena en un estado de Recoil que se comparte en toda la aplicación:
|
||||
Internamente, el ámbito seleccionado se almacena en un estado de Jotai que se comparte en toda la aplicación:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
¡Pero este estado de Recoil nunca debe manejarse manualmente! Veremos cómo usarlo en la siguiente sección.
|
||||
¡Pero este estado de Jotai nunca debe manejarse manualmente! Veremos cómo usarlo en la siguiente sección.
|
||||
|
||||
## ¿Cómo funciona internamente?
|
||||
|
||||
Hicimos un contenedor delgado sobre [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) que lo hace más eficiente y evita renders innecesarios.
|
||||
|
||||
También creamos un estado de Recoil para manejar el estado del ámbito de atajos de teclado y hacerlo disponible en toda la aplicación.
|
||||
También creamos un estado de Jotai para manejar el estado del ámbito de atajos de teclado y hacerlo disponible en toda la aplicación.
|
||||
|
||||
@@ -12,7 +12,6 @@ Un selector de íconos basado en un menú desplegable que permite a los usuarios
|
||||
<Tabs>
|
||||
<Tab title="Uso">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -25,14 +24,12 @@ Un selector de íconos basado en un menú desplegable que permite a los usuarios
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ Permite a los usuarios seleccionar un valor de una lista de opciones predefinida
|
||||
<Tabs>
|
||||
<Tab title="Uso">
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -20,7 +19,6 @@ Permite a los usuarios seleccionar un valor de una lista de opciones predefinida
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -31,7 +29,6 @@ Permite a los usuarios seleccionar un valor de una lista de opciones predefinida
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ image: '"/images/user-guide/notes/notes_header.png"'
|
||||
<Tabs>
|
||||
<Tab title=""Uso"">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -27,7 +26,6 @@ image: '"/images/user-guide/notes/notes_header.png"'
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Nombre de usuario"
|
||||
@@ -38,7 +36,6 @@ image: '"/images/user-guide/notes/notes_header.png"'
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
},{
|
||||
@@ -68,12 +65,10 @@ image: '"/images/user-guide/notes/notes_header.png"'
|
||||
<Tabs>
|
||||
<Tab title=""Uso"">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("Función onValidate ejecutada")}
|
||||
minRows={1}
|
||||
@@ -83,7 +78,6 @@ image: '"/images/user-guide/notes/notes_header.png"'
|
||||
buttonTitle
|
||||
value="Tarea: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Ce document décrit les meilleures pratiques à suivre lors de votre travail sur
|
||||
|
||||
## Gestion de l'état
|
||||
|
||||
React et Recoil gèrent la gestion de l'état dans la base de code.
|
||||
React et Jotai gèrent la gestion de l'état dans la base de code.
|
||||
|
||||
### Utilisez `useRecoilState` pour stocker l'état
|
||||
### Utilisez `useAtomState` pour stocker l'état
|
||||
|
||||
C'est une bonne pratique de créer autant d'atomes que nécessaire pour stocker votre état.
|
||||
|
||||
@@ -17,13 +17,16 @@ C'est une bonne pratique de créer autant d'atomes que nécessaire pour stocker
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -40,7 +43,7 @@ export const MyComponent = () => {
|
||||
|
||||
Évitez d'utiliser `useRef` pour stocker l'état.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
Consultez [comment gérer les re-rendus](#managing-re-renders) si vous avez l'impression d'avoir besoin de `useRef` pour empêcher certains re-rendus.
|
||||
|
||||
@@ -80,8 +83,8 @@ Vous pouvez appliquer la même chose à la logique de récupération de données
|
||||
// ❌ Mauvais, provoquera de nouveaux rendus même si les données ne changent pas,
|
||||
// car useEffect doit être réévalué
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -93,9 +96,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -103,14 +104,14 @@ export const App = () => (
|
||||
// ✅ Bon, ne provoquera pas de nouveaux rendus si les données ne changent pas,
|
||||
// car useEffect est réévalué dans un autre composant frère
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -122,16 +123,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Utilisez les états de famille de recoil et les sélecteurs de famille de recoil
|
||||
### Utilisez les états de famille de jotai et les sélecteurs de famille de jotai
|
||||
|
||||
Les états et sélecteurs de famille recoil sont un excellent moyen d'éviter les re-rendus.
|
||||
Les états et sélecteurs de famille jotai sont un excellent moyen d'éviter les re-rendus.
|
||||
|
||||
Ils sont utiles lorsque vous devez stocker une liste d'articles.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Voir [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) pour plus
|
||||
|
||||
### États
|
||||
|
||||
Contient la logique de gestion des états. [RecoilJS](https://recoiljs.org) gère cela.
|
||||
Contient la logique de gestion des états. [Jotai](https://jotai.org) gère cela.
|
||||
|
||||
* Sélecteurs : Voir [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) pour plus de détails.
|
||||
* Sélecteurs : Les atomes dérivés (via `createAtomSelector`) calculent des valeurs à partir d'autres atomes et sont automatiquement mémoïsés.
|
||||
|
||||
La gestion de l'état intégrée de React gère toujours l'état au sein d'un composant.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Le projet a une stack simple et propre, avec un code boilerplate minimal.
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Tests**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/fr/developers/contribute/capabilities/front
|
||||
|
||||
### Gestion de l'État
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) gère la gestion de l'état.
|
||||
[Jotai](https://jotai.org/) gère la gestion de l'état.
|
||||
|
||||
Voir [les meilleures pratiques](/l/fr/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pour plus d'informations sur la gestion de l'état.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
En interne, le périmètre sélectionné est stocké dans un état Recoil qui est partagé dans toute l'application :
|
||||
En interne, le périmètre sélectionné est stocké dans un état Jotai qui est partagé dans toute l'application :
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Mais cet état Recoil ne doit jamais être manipulé manuellement ! Nous verrons comment l'utiliser dans la prochaine section.
|
||||
Mais cet état Jotai ne doit jamais être manipulé manuellement ! Nous verrons comment l'utiliser dans la prochaine section.
|
||||
|
||||
## Comment cela fonctionne-t-il en interne ?
|
||||
|
||||
Nous avons créé un léger emballage au-dessus de [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) qui le rend plus performant et évite les rendus inutiles.
|
||||
|
||||
Nous créons également un état Recoil pour gérer l'état du périmètre des raccourcis et le rendre disponible partout dans l'application.
|
||||
Nous créons également un état Jotai pour gérer l'état du périmètre des raccourcis et le rendre disponible partout dans l'application.
|
||||
|
||||
@@ -12,7 +12,6 @@ Un sélecteur d'icônes basé sur un menu déroulant qui permet aux utilisateurs
|
||||
<Tabs>
|
||||
<Tab title="Utilisation">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -25,14 +24,12 @@ Un sélecteur d'icônes basé sur un menu déroulant qui permet aux utilisateurs
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ Permet aux utilisateurs de choisir une valeur parmi une liste d'options prédéf
|
||||
<Tabs>
|
||||
<Tab title="Utilisation">
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -20,7 +19,6 @@ Permet aux utilisateurs de choisir une valeur parmi une liste d'options prédéf
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -31,7 +29,6 @@ Permet aux utilisateurs de choisir une valeur parmi une liste d'options prédéf
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ Permet aux utilisateurs de saisir et de modifier du texte.
|
||||
<Tabs>
|
||||
<Tab title="Utilisation">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -27,7 +26,6 @@ Permet aux utilisateurs de saisir et de modifier du texte.
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -38,7 +36,6 @@ Permet aux utilisateurs de saisir et de modifier du texte.
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -68,12 +65,10 @@ Composant d'entrée de texte qui ajuste automatiquement sa hauteur en fonction d
|
||||
<Tabs>
|
||||
<Tab title="Utilisation">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -83,7 +78,6 @@ Composant d'entrée de texte qui ajuste automatiquement sa hauteur en fonction d
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Questo documento descrive le migliori pratiche da seguire quando si lavora sul f
|
||||
|
||||
## Gestione dello Stato
|
||||
|
||||
React e Recoil gestiscono la gestione dello stato nella base di codice.
|
||||
React e Jotai gestiscono la gestione dello stato nella base di codice.
|
||||
|
||||
### Usa `useRecoilState` per memorizzare lo stato
|
||||
### Usa `useAtomState` per memorizzare lo stato
|
||||
|
||||
È buona pratica creare tanti atomi quanti servono per memorizzare il tuo stato.
|
||||
|
||||
@@ -19,13 +19,16 @@ React e Recoil gestiscono la gestione dello stato nella base di codice.
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Evita di usare `useRef` per memorizzare lo stato.
|
||||
|
||||
Se vuoi memorizzare lo stato, dovresti usare `useState` o `useRecoilState`.
|
||||
Se vuoi memorizzare lo stato, dovresti usare `useState` o `useAtomState`.
|
||||
|
||||
Consulta [come gestire i re-render](#managing-re-renders) se senti che hai bisogno di `useRef` per evitare alcuni re-render.
|
||||
|
||||
@@ -82,8 +85,8 @@ Puoi applicare lo stesso per la logica di recupero dati, con i hook di Apollo.
|
||||
// ❌ Sconsigliato, causerà re-render anche se i dati non cambiano,
|
||||
// perché useEffect deve essere ri-eseguito
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Consigliato, non causerà re-render se i dati non cambiano,
|
||||
// perché useEffect viene ri-eseguito in un altro componente fratello
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Usa stati di famiglia recoil e selettori di famiglia recoil
|
||||
### Usa stati di famiglia jotai e selettori di famiglia jotai
|
||||
|
||||
Gli stati e i selettori di famiglia Recoil sono un ottimo modo per evitare re-render.
|
||||
Gli stati e i selettori di famiglia Jotai sono un ottimo modo per evitare re-render.
|
||||
|
||||
Sono utili quando hai bisogno di memorizzare una lista di elementi.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Vedi [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) per ulteri
|
||||
|
||||
### Stati
|
||||
|
||||
Contiene la logica di gestione degli stati. [RecoilJS](https://recoiljs.org) se ne occupa.
|
||||
Contiene la logica di gestione degli stati. [Jotai](https://jotai.org) se ne occupa.
|
||||
|
||||
* Selettori: Vedi [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) per ulteriori dettagli.
|
||||
* Selettori: Gli atomi derivati (tramite `createAtomSelector`) calcolano valori da altri atomi e sono automaticamente memorizzati.
|
||||
|
||||
La gestione degli stati integrata di React si occupa ancora dello stato all'interno di un componente.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Il progetto ha una struttura chiara e semplice, con un codice boilerplate minimo
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testing**
|
||||
@@ -77,7 +77,7 @@ Per evitare [re-render](/l/it/developers/contribute/capabilities/frontend-develo
|
||||
|
||||
### Gestione dello stato
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) gestisce lo stato.
|
||||
[Jotai](https://jotai.org/) gestisce lo stato.
|
||||
|
||||
Vedi [best practices](/l/it/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) per ulteriori informazioni sulla gestione dello stato.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Internamente, l'ambito selezionato attualmente viene memorizzato in uno stato Recoil condiviso in tutta l'applicazione:
|
||||
Internamente, l'ambito selezionato attualmente viene memorizzato in uno stato Jotai condiviso in tutta l'applicazione:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Ma questo stato Recoil non dovrebbe mai essere gestito manualmente! Vedremo come usarlo nella sezione successiva.
|
||||
Ma questo stato Jotai non dovrebbe mai essere gestito manualmente! Vedremo come usarlo nella sezione successiva.
|
||||
|
||||
## Come funziona internamente?
|
||||
|
||||
Abbiamo creato un sottile wrapper su [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) che lo rende più performante ed evita rendering non necessari.
|
||||
|
||||
Abbiamo anche creato uno stato Recoil per gestire lo stato dell'ambito del tasto di scelta rapida e renderlo disponibile ovunque nell'applicazione.
|
||||
Abbiamo anche creato uno stato Jotai per gestire lo stato dell'ambito del tasto di scelta rapida e renderlo disponibile ovunque nell'applicazione.
|
||||
|
||||
@@ -14,7 +14,6 @@ Un selettore di icone basato su menu a tendina che consente agli utenti di scegl
|
||||
<Tab title="Utilizzo">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Permette agli utenti di scegliere un valore da un elenco di opzioni predefinite.
|
||||
<Tab title="Utilizzo">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Consente agli utenti di inserire e modificare il testo.
|
||||
<Tab title="Utilizzo">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ Componente di input testo che regola automaticamente la sua altezza in base al c
|
||||
<Tab title="Utilizzo">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ title: ベストプラクティス',
|
||||
|
||||
## 状態管理
|
||||
|
||||
React と Recoil はコードベース内の状態管理を行います。
|
||||
React と Jotai はコードベース内の状態管理を行います。
|
||||
|
||||
### 状態を保存するために `useRecoilState` を使用する
|
||||
### 状態を保存するために `useAtomState` を使用する
|
||||
|
||||
状態を保存するために必要なだけ多くのアトムを作成するのがよいです。
|
||||
|
||||
@@ -17,13 +17,16 @@ React と Recoil はコードベース内の状態管理を行います。
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -40,7 +43,7 @@ export const MyComponent = () => {
|
||||
|
||||
状態の保存に `useRef` を使用するのは避けてください。
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
いくつかの再レンダリングを防ぐために `useRef` が必要だと感じた場合は、[再レンダリングの管理方法](#managing-re-renders)を参照してください。
|
||||
|
||||
@@ -80,8 +83,8 @@ Apollo フックを使用してデータ取得ロジックにも同じことを
|
||||
// ❌ 悪い例: データが変化していなくても再レンダーを引き起こす
|
||||
// useEffect を再評価する必要があるため
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -93,9 +96,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -103,14 +104,14 @@ export const App = () => (
|
||||
// ✅ 良い例: データが変化していなければ再レンダーは発生しない
|
||||
// useEffect が別の兄弟コンポーネントで再評価されるため
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -122,16 +123,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Recoilファミリー状態とファミリーセレクターを使用する
|
||||
### Jotaiファミリー状態とファミリーセレクターを使用する
|
||||
|
||||
Recoil ファミリー状態とセレクターは、再レンダリングを回避するための優れた方法です。
|
||||
Jotai ファミリー状態とセレクターは、再レンダリングを回避するための優れた方法です。
|
||||
|
||||
アイテムのリストを保存する必要があるときに有用です。
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ module1
|
||||
|
||||
### ステート
|
||||
|
||||
ステート管理のロジックを含みます。 [RecoilJS](https://recoiljs.org) がこれを管理します。
|
||||
ステート管理のロジックを含みます。 [Jotai](https://jotai.org) がこれを管理します。
|
||||
|
||||
* セレクター: 詳細は[RecoilJSセレクター](https://recoiljs.org/docs/basic-tutorial/selectors)を参照してください。
|
||||
* セレクター: 派生アトム(`createAtomSelector`を使用)は他のアトムから値を計算し、自動的にメモ化されます。
|
||||
|
||||
Reactの組み込みステート管理は依然としてコンポーネント内のステートを処理します。
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**テスト**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/ja/developers/contribute/capabilities/front
|
||||
|
||||
### 状態管理
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts)は状態管理を処理します。
|
||||
[Jotai](https://jotai.org/)は状態管理を処理します。
|
||||
|
||||
状態管理に関する詳細な情報は[ベストプラクティス](/l/ja/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)を参照してください。
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
内部的には、現在選択されているスコープはアプリケーション全体で共有されるRecoilステートに格納されています:
|
||||
内部的には、現在選択されているスコープはアプリケーション全体で共有されるJotaiステートに格納されています:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
しかし、このRecoilステートは手動で処理しないでください! 次のセクションでその使用方法を見ていきます。 次のセクションでその使用方法を見ていきます。 次のセクションでその使用方法を見ていきます。
|
||||
しかし、このJotaiステートは手動で処理しないでください! 次のセクションでその使用方法を見ていきます。 次のセクションでその使用方法を見ていきます。 次のセクションでその使用方法を見ていきます。
|
||||
|
||||
## 内部的にはどう機能しているのか?
|
||||
|
||||
[react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro)の上に薄いラッパーを作成し、より効率的にし、不必要な再レンダリングを避けます。
|
||||
|
||||
また、ホットキースコープの状態を処理し、アプリケーション全体で利用できるRecoilステートを作成しました。
|
||||
また、ホットキースコープの状態を処理し、アプリケーション全体で利用できるJotaiステートを作成しました。
|
||||
|
||||
@@ -12,7 +12,6 @@ image: /images/user-guide/github/github-header.png
|
||||
<Tabs>
|
||||
<Tab title="使用方法">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -25,14 +24,12 @@ image: /images/user-guide/github/github-header.png
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
<Tabs>
|
||||
<Tab title="使用方法">
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -20,7 +19,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -31,7 +29,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tabs>
|
||||
<Tab title="使用方法">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -27,7 +26,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="ユーザー名"
|
||||
@@ -38,7 +36,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -68,12 +65,10 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tabs>
|
||||
<Tab title="使用方法">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -83,7 +78,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ title: 모범 사례
|
||||
|
||||
## 상태 관리
|
||||
|
||||
React와 Recoil은 코드베이스에서 상태 관리를 처리합니다.
|
||||
React와 Jotai는 코드베이스에서 상태 관리를 처리합니다.
|
||||
|
||||
### `useRecoilState`로 상태 저장하기
|
||||
### `useAtomState`로 상태 저장하기
|
||||
|
||||
상태를 저장하는 데 필요한 만큼의 atom을 만드는 것이 좋은 습관입니다.
|
||||
|
||||
@@ -17,13 +17,16 @@ React와 Recoil은 코드베이스에서 상태 관리를 처리합니다.
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -40,7 +43,7 @@ export const MyComponent = () => {
|
||||
|
||||
상태 저장에 `useRef`를 사용하지 않도록 주의하십시오.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
일부 리렌더링을 방지하기 위해 `useRef`가 필요하다고 느낄 경우 [리렌더링 관리 방법](#managing-re-renders)을 참조하십시오.
|
||||
|
||||
@@ -80,8 +83,8 @@ Apollo 훅을 사용하여 데이터 페칭 로직에 동일한 규칙을 적용
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
// because useEffect needs to be re-evaluated
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -93,9 +96,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -103,14 +104,14 @@ export const App = () => (
|
||||
// ✅ Good, will not cause re-renders if data is not changing,
|
||||
// because useEffect is re-evaluated in another sibling component
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -122,16 +123,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Recoil 가족 상태 및 Recoil 가족 선택자 사용하기
|
||||
### Jotai 가족 상태 및 Jotai 가족 선택자 사용하기
|
||||
|
||||
Recoil 가족 상태와 선택자는 리렌더링을 피하기 위한 훌륭한 방법입니다.
|
||||
Jotai 가족 상태와 선택자는 리렌더링을 피하기 위한 훌륭한 방법입니다.
|
||||
|
||||
항목 목록을 저장해야 할 때 유용합니다.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ module1
|
||||
|
||||
### 상태
|
||||
|
||||
상태 관리 로직이 포함되어 있습니다. [RecoilJS](https://recoiljs.org)가 이것을 처리합니다.
|
||||
상태 관리 로직이 포함되어 있습니다. [Jotai](https://jotai.org)가 이것을 처리합니다.
|
||||
|
||||
* 셀렉터: 자세한 내용은 [RecoilJS 셀렉터](https://recoiljs.org/docs/basic-tutorial/selectors)를 참조하세요.
|
||||
* 셀렉터: 파생 아톰(`createAtomSelector` 사용)은 다른 아톰에서 값을 계산하며 자동으로 메모이제이션됩니다.
|
||||
|
||||
React의 내장 상태 관리는 구성 요소 내에서의 상태를 여전히 처리합니다.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**테스트**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/ko/developers/contribute/capabilities/front
|
||||
|
||||
### 상태 관리
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts)이 상태 관리를 처리합니다.
|
||||
[Jotai](https://jotai.org/)이 상태 관리를 처리합니다.
|
||||
|
||||
상태 관리에 대한 자세한 정보는 [최고의 관례](/l/ko/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)를 참조하십시오.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
내부적으로, 현재 선택한 스코프는 애플리케이션 전반에 걸쳐 공유되는 Recoil 상태에 저장됩니다:
|
||||
내부적으로, 현재 선택한 스코프는 애플리케이션 전반에 걸쳐 공유되는 Jotai 상태에 저장됩니다:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
하지만 이 Recoil 상태는 수동으로 처리해서는 안 됩니다! 다음 섹션에서 사용하는 방법을 배웁니다.
|
||||
하지만 이 Jotai 상태는 수동으로 처리해서는 안 됩니다! 다음 섹션에서 사용하는 방법을 배웁니다.
|
||||
|
||||
## 내부적으로 어떻게 작동합니까?
|
||||
|
||||
[react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) 위에 얇은 래퍼를 만들어 성능을 높이고 불필요한 재랜더링을 방지합니다.
|
||||
|
||||
또한 핫키 스코프 상태를 처리하고 애플리케이션 전반에서 사용할 수 있도록 한 Recoil 상태를 만듭니다.
|
||||
또한 핫키 스코프 상태를 처리하고 애플리케이션 전반에서 사용할 수 있도록 한 Jotai 상태를 만듭니다.
|
||||
|
||||
@@ -12,7 +12,6 @@ image: /images/user-guide/github/github-header.png
|
||||
<Tabs>
|
||||
<Tab title="사용법">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -25,14 +24,12 @@ image: /images/user-guide/github/github-header.png
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
<Tabs>
|
||||
<Tab title="사용법">
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -20,7 +19,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -31,7 +29,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tabs>
|
||||
<Tab title="사용법">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -27,7 +26,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="사용자 이름"
|
||||
@@ -38,7 +36,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -67,12 +64,10 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tabs>
|
||||
<Tab title="사용법">
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate 함수 실행됨")}
|
||||
minRows={1}
|
||||
@@ -82,7 +77,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
buttonTitle
|
||||
value="작업: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Este documento descreve as melhores práticas que você deve seguir ao trabalhar
|
||||
|
||||
## Gerenciamento de Estado
|
||||
|
||||
React e Recoil lidam com o gerenciamento de estado na base de código.
|
||||
React e Jotai lidam com o gerenciamento de estado na base de código.
|
||||
|
||||
### Use `useRecoilState` para armazenar o estado
|
||||
### Use `useAtomState` para armazenar o estado
|
||||
|
||||
É uma boa prática criar tantos átomos quanto necessário para armazenar seu estado.
|
||||
|
||||
@@ -19,13 +19,16 @@ React e Recoil lidam com o gerenciamento de estado na base de código.
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Evite usar `useRef` para armazenar estado.
|
||||
|
||||
If you want to store state, you should use `useState` or `useRecoilState`.
|
||||
If you want to store state, you should use `useState` or `useAtomState`.
|
||||
|
||||
Veja [como gerenciar re-renderizações](#managing-re-renders) se você sentir que precisa de `useRef` para evitar que algumas re-renderizações aconteçam.
|
||||
|
||||
@@ -82,8 +85,8 @@ Você pode aplicar o mesmo para lógica de busca de dados, com hooks do Apollo.
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
// because useEffect needs to be re-evaluated
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Good, will not cause re-renders if data is not changing,
|
||||
// because useEffect is re-evaluated in another sibling component
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Use estados de família Recoil e seletores de família Recoil
|
||||
### Use estados de família Jotai e seletores de família Jotai
|
||||
|
||||
Estados de família Recoil e seletores são uma ótima maneira de evitar re-renderizações.
|
||||
Estados de família Jotai e seletores são uma ótima maneira de evitar re-renderizações.
|
||||
|
||||
Eles são úteis quando você precisa armazenar uma lista de itens.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Veja [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) para mais
|
||||
|
||||
### Estados
|
||||
|
||||
Contém a lógica de gerenciamento de estado. [RecoilJS](https://recoiljs.org) lida com isso.
|
||||
Contém a lógica de gerenciamento de estado. [Jotai](https://jotai.org) lida com isso.
|
||||
|
||||
* Seletores: Veja [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) para mais detalhes.
|
||||
* Seletores: Átomos derivados (usando `createAtomSelector`) calculam valores a partir de outros átomos e são automaticamente memorizados.
|
||||
|
||||
O gerenciamento de estado embutido do React ainda lida com o estado dentro de um componente.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ O projeto possui uma pilha limpa e simples, com pouco código boilerplate.
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testes**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/pt/developers/contribute/capabilities/front
|
||||
|
||||
### Gerenciamento de Estado
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) gerencia o estado.
|
||||
[Jotai](https://jotai.org/) gerencia o estado.
|
||||
|
||||
Veja [melhores práticas](/l/pt/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) para mais informações sobre gerenciamento de estado.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Internamente, o escopo atualmente selecionado é armazenado em um estado Recoil que é compartilhado por toda a aplicação :
|
||||
Internamente, o escopo atualmente selecionado é armazenado em um estado Jotai que é compartilhado por toda a aplicação :
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Mas esse estado Recoil nunca deve ser manipulado manualmente! Veremos como usá-lo na próxima seção.
|
||||
Mas esse estado Jotai nunca deve ser manipulado manualmente! Veremos como usá-lo na próxima seção.
|
||||
|
||||
## Como funciona internamente?
|
||||
|
||||
Criamos um wrapper leve em cima de [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) que o torna mais eficiente e evita renderizações desnecessárias.
|
||||
|
||||
Também criamos um estado Recoil para gerenciar o estado do escopo da tecla de atalho e torná-lo disponível em toda a aplicação.
|
||||
Também criamos um estado Jotai para gerenciar o estado do escopo da tecla de atalho e torná-lo disponível em toda a aplicação.
|
||||
|
||||
@@ -14,7 +14,6 @@ Um seletor de ícones baseado em lista suspensa que permite aos usuários seleci
|
||||
<Tab title="Uso">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Permite aos utilizadores escolher um valor a partir de uma lista de opções pr
|
||||
<Tab title="Uso">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -16,7 +16,6 @@ Permite aos usuários inserir e editar texto.
|
||||
<Tab title="Uso">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ Componente de entrada de texto que ajusta automaticamente sua altura com base no
|
||||
<Tab title="Uso">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Acest document prezintă cele mai bune practici pe care ar trebui să le urmați
|
||||
|
||||
## Managementul stării
|
||||
|
||||
React și Recoil se ocupă de managementul stării în cod.
|
||||
React și Jotai se ocupă de managementul stării în cod.
|
||||
|
||||
### Folosiți `useRecoilState` pentru a stoca starea
|
||||
### Folosiți `useAtomState` pentru a stoca starea
|
||||
|
||||
Este o bună practică să creezi atâția atomi câți ai nevoie pentru a-ți stoca starea.
|
||||
|
||||
@@ -19,13 +19,16 @@ Este mai bine să folosești atomi suplimentari decât să încerci să fii prea
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Evitați utilizarea `useRef` pentru a stoca starea.
|
||||
|
||||
Dacă doriți să stocați starea, ar trebui să folosiți `useState` sau `useRecoilState`.
|
||||
Dacă doriți să stocați starea, ar trebui să folosiți `useState` sau `useAtomState`.
|
||||
|
||||
Vezi [cum să gestionezi re-randările](#managing-re-renders) dacă ți se pare că ai nevoie de `useRef` pentru a preveni apariția unor re-randări.
|
||||
|
||||
@@ -82,8 +85,8 @@ Puteți aplica același principiu pentru logica de interogare de date, folosind
|
||||
// ❌ Greșit, va provoca re-randări chiar dacă datele nu se schimbă,
|
||||
// deoarece useEffect trebuie re-evaluat
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Bun, nu va provoca re-randări dacă datele nu se schimbă,
|
||||
// deoarece useEffect este re-evaluat într-o altă componentă la același nivel
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Folosiți stări de familie și selectoare de familie cu recoil
|
||||
### Folosiți stări de familie și selectoare de familie cu jotai
|
||||
|
||||
Stările și selectoarele de familie cu recoil sunt o metodă excelentă de a evita re-render-urile.
|
||||
Stările și selectoarele de familie cu jotai sunt o metodă excelentă de a evita re-render-urile.
|
||||
|
||||
Sunt utile când trebuie să stocați o listă de elemente.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Vezi [Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks) pentru mai
|
||||
|
||||
### Stări
|
||||
|
||||
Conține logica de gestionare a stării. [RecoilJS](https://recoiljs.org) gestionează aceasta.
|
||||
Conține logica de gestionare a stării. [Jotai](https://jotai.org) gestionează aceasta.
|
||||
|
||||
* Selectori: Vezi [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) pentru mai multe detalii.
|
||||
* Selectori: Atomii derivați (folosind `createAtomSelector`) calculează valori din alți atomi și sunt memorați automat.
|
||||
|
||||
Managementul de stare încorporat în React gestionează încă starea în cadrul unei componente.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Proiectul are un stack curat și simplu, cu cod boilerplate minim.
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Testare**
|
||||
@@ -77,7 +77,7 @@ Pentru a evita [re-redări](/l/ro/developers/contribute/capabilities/frontend-de
|
||||
|
||||
### Managementul stării
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) se ocupă de managementul stării.
|
||||
[Jotai](https://jotai.org/) se ocupă de managementul stării.
|
||||
|
||||
Consultați [cele mai bune practici](/l/ro/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) pentru mai multe informații despre managementul stării.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Intern, domeniul selectat în prezent este stocat într-o stare Recoil care este partajată în toată aplicația:
|
||||
Intern, domeniul selectat în prezent este stocat într-o stare Jotai care este partajată în toată aplicația:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Însă această stare Recoil nu ar trebui să fie gestionată manual! Vom vedea cum să o folosim în secțiunea următoare.
|
||||
Însă această stare Jotai nu ar trebui să fie gestionată manual! Vom vedea cum să o folosim în secțiunea următoare.
|
||||
|
||||
## Cum funcționează intern?
|
||||
|
||||
Am făcut un wrapper subțire peste [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) care îl face mai performant și evită re-rendările inutile.
|
||||
|
||||
De asemenea, creăm o stare Recoil pentru a gestiona starea domeniului comenzilor rapide și să fie disponibilă oriunde în aplicație.
|
||||
De asemenea, creăm o stare Jotai pentru a gestiona starea domeniului comenzilor rapide și să fie disponibilă oriunde în aplicație.
|
||||
|
||||
@@ -14,7 +14,6 @@ Un selector de iconițe bazat pe listă derulantă care permite utilizatorilor s
|
||||
<Tab title="Utilizare">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Permite utilizatorilor să aleagă o valoare dintr-o listă de opțiuni predefin
|
||||
<Tab title="Utilizare">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Permite utilizatorilor să introducă și să editeze text.
|
||||
<Tab title="Utilizare">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ Componenta de intrare text care își ajustează automat înălțimea în funcț
|
||||
<Tab title="Utilizare">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ title: Лучшие практики
|
||||
|
||||
## Управление состоянием
|
||||
|
||||
React и Recoil отвечают за управление состоянием в коде.
|
||||
React и Jotai отвечают за управление состоянием в коде.
|
||||
|
||||
### Используйте `useRecoilState` для хранения состояния
|
||||
### Используйте `useAtomState` для хранения состояния
|
||||
|
||||
Полезно создавать столько атомов, сколько вам нужно для хранения состояния.
|
||||
|
||||
@@ -19,13 +19,16 @@ React и Recoil отвечают за управление состоянием
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Избегайте использования `useRef` для хранения состояния.
|
||||
|
||||
Если вы хотите сохранить состояние, вам следует использовать `useState` или `useRecoilState`.
|
||||
Если вы хотите сохранить состояние, вам следует использовать `useState` или `useAtomState`.
|
||||
|
||||
Смотрите [как управлять повторными рендерами](#managing-re-renders), если вы считаете, что вам нужен `useRef`, чтобы предотвратить их.
|
||||
|
||||
@@ -82,8 +85,8 @@ export const MyComponent = () => {
|
||||
// ❌ Bad, will cause re-renders even if data is not changing,
|
||||
// because useEffect needs to be re-evaluated
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ Good, will not cause re-renders if data is not changing,
|
||||
// because useEffect is re-evaluated in another sibling component
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Используйте состояния семейства Recoil и селекторы семейства Recoil
|
||||
### Используйте состояния семейства Jotai и селекторы семейства Jotai
|
||||
|
||||
Состояния семейства Recoil и селекторы — отличный способ избежать повторных рендеров.
|
||||
Состояния семейства Jotai и селекторы — отличный способ избежать повторных рендеров.
|
||||
|
||||
Они полезны, когда нужно хранить список элементов.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ module1
|
||||
|
||||
### Состояния
|
||||
|
||||
Содержит логику управления состоянием. [RecoilJS](https://recoiljs.org) этим управляет.
|
||||
Содержит логику управления состоянием. [Jotai](https://jotai.org) этим управляет.
|
||||
|
||||
* Селекторы: См. [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors) для более подробной информации.
|
||||
* Селекторы: Производные атомы (с использованием `createAtomSelector`) вычисляют значения из других атомов и автоматически мемоизируются.
|
||||
|
||||
Встроенное управление состоянием в React все еще управляет состоянием внутри компонента.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ npx nx run twenty-front:storybook:coverage # (требуется yarn storybook:
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Тестирование**
|
||||
@@ -77,7 +77,7 @@ npx nx run twenty-front:storybook:coverage # (требуется yarn storybook:
|
||||
|
||||
### Управление состоянием
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) обрабатывает управление состоянием.
|
||||
[Jotai](https://jotai.org/) обрабатывает управление состоянием.
|
||||
|
||||
[лучшие практики](/l/ru/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) для получения дополнительной информации об управлении состоянием.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Внутренне текущая выбранная область хранится в состоянии Recoil, которое используется по всему приложению:
|
||||
Внутренне текущая выбранная область хранится в состоянии Jotai, которое используется по всему приложению:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Но это состояние Recoil никогда не следует обрабатывать вручную! Мы увидим, как использовать это в следующем разделе.
|
||||
Но это состояние Jotai никогда не следует обрабатывать вручную! Мы увидим, как использовать это в следующем разделе.
|
||||
|
||||
## Как это работает внутренне?
|
||||
|
||||
Мы сделали тонкую обертку поверх [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro), которая делает его более производительным и избегает ненужных повторных рендеров.
|
||||
|
||||
Мы также создаем состояние Recoil, чтобы управлять состоянием горячей клавиши и сделать его доступным везде в приложении.
|
||||
Мы также создаем состояние Jotai, чтобы управлять состоянием горячей клавиши и сделать его доступным везде в приложении.
|
||||
|
||||
@@ -14,7 +14,6 @@ image: /images/user-guide/github/github-header.png
|
||||
<Tab title="Использование">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
<Tab title="Использование">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tab title="Использование">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Username"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -81,12 +78,10 @@ export const MyComponent = () => {
|
||||
<Tab title="Использование">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate function fired")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Task: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ Bu belge, ön yüz üzerinde çalışırken takip etmeniz gereken en iyi uygulam
|
||||
|
||||
## Durum Yönetimi
|
||||
|
||||
React ve Recoil, kod tabanında durumu yönetir.
|
||||
React ve Jotai, kod tabanında durumu yönetir.
|
||||
|
||||
### Durumu depolamak için `useRecoilState` kullanın.
|
||||
### Durumu depolamak için `useAtomState` kullanın.
|
||||
|
||||
Durumunuzu depolamak için ihtiyaç duyduğunuz kadar atom oluşturmak iyi bir uygulamadır.
|
||||
|
||||
@@ -19,13 +19,16 @@ Prop drilling ile gereğinden fazla sade olmaya çalışmaktansa, fazladan atom
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
Durum saklamak için `useRef` kullanmaktan kaçının.
|
||||
|
||||
Durum saklamak istiyorsanız, `useState` veya `useRecoilState` kullanmalısınız.
|
||||
Durum saklamak istiyorsanız, `useState` veya `useAtomState` kullanmalısınız.
|
||||
|
||||
Bazı yeniden render edilmelerin olmasını önlemek için `useRef`'e ihtiyacınız varmış gibi hissediyorsanız, [yeniden render yönetimi](#managing-re-renders) konusuna bakın.
|
||||
|
||||
@@ -82,8 +85,8 @@ Aynısını Apollo kancaları ile veri çekme mantığı için de uygulayabilirs
|
||||
// ❌ Kötü, veri değişmese bile yeniden render'a neden olacak,
|
||||
// çünkü useEffect'in yeniden değerlendirilmesi gerekiyor
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ İyi, veri değişmiyorsa yeniden render'a neden olmaz,
|
||||
// çünkü useEffect başka bir kardeş bileşende yeniden değerlendirilir
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### Recoil aile durumlarını ve recoil aile seçimcilerini kullanın.
|
||||
### Jotai aile durumlarını ve jotai aile seçimcilerini kullanın.
|
||||
|
||||
Recoil aile durumları ve seçimcileri, yeniden render'ları önlemenin harika bir yoludur.
|
||||
Jotai aile durumları ve seçimcileri, yeniden render'ları önlemenin harika bir yoludur.
|
||||
|
||||
Bir öğe listesini saklamanız gerektiğinde kullanılabilirdir.
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ Daha fazla bilgi için [Kancalar](https://react.dev/learn/reusing-logic-with-cus
|
||||
|
||||
### Durumlar
|
||||
|
||||
Durum yönetim mantığını içerir. [RecoilJS](https://recoiljs.org) bunu ele almaktadır.
|
||||
Durum yönetim mantığını içerir. [Jotai](https://jotai.org) bunu ele almaktadır.
|
||||
|
||||
* Seçiciler: Daha fazla bilgi için [RecoilJS Seçiciler](https://recoiljs.org/docs/basic-tutorial/selectors) sayfasına bakın.
|
||||
* Seçiciler: Türetilmiş atomlar (`createAtomSelector` kullanılarak) diğer atomlardan değer hesaplar ve otomatik olarak önbelleğe alınır.
|
||||
|
||||
React'ın yerleşik durum yönetimi, bir bileşen içinde hala durumu ele alır.
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ Proje temiz ve basit bir yığına sahip, minimum şablon koduyla.
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL Codegen](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**Test**
|
||||
@@ -77,7 +77,7 @@ Gereksiz [yeniden renderların](/l/tr/developers/contribute/capabilities/fronten
|
||||
|
||||
### Durum Yönetimi
|
||||
|
||||
Durum yönetimini [Recoil](https://recoiljs.org/docs/introduction/core-concepts) halleder.
|
||||
Durum yönetimini [Jotai](https://jotai.org/) halleder.
|
||||
|
||||
Durum yönetimi hakkında daha fazla bilgi için [en iyi uygulamalar](/l/tr/developers/contribute/capabilities/frontend-development/best-practices-front#state-management) bölümüne bakın.
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
Dahili olarak, şu anda seçili olan kapsam, uygulama genelinde paylaşılan bir Recoil durumunda saklanır:
|
||||
Dahili olarak, şu anda seçili olan kapsam, uygulama genelinde paylaşılan bir Jotai durumunda saklanır:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
Ancak bu Recoil durumu asla el ile yönetilmemelidir! Bunu bir sonraki bölümde nasıl kullanacağımızı göreceğiz.
|
||||
Ancak bu Jotai durumu asla el ile yönetilmemelidir! Bunu bir sonraki bölümde nasıl kullanacağımızı göreceğiz.
|
||||
|
||||
## İçsel olarak nasıl çalışıyor?
|
||||
|
||||
Gereksiz yeniden render etme işlemlerinden kaçınarak daha performanslı hale getiren [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) üzerine ince bir sarmalayıcı yaptık.
|
||||
|
||||
Ayrıca, kısayol kapsamı durumunu yönetmek ve uygulamanın her yerinde kullanılabilir hale getirmek için bir Recoil durumu oluşturuyoruz.
|
||||
Ayrıca, kısayol kapsamı durumunu yönetmek ve uygulamanın her yerinde kullanılabilir hale getirmek için bir Jotai durumu oluşturuyoruz.
|
||||
|
||||
@@ -14,7 +14,6 @@ Kullanıcıların bir listeden simge seçmesine olanak tanıyan bir açılır me
|
||||
<Tab title="Kullanım">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ Kullanıcılara önceden tanımlanmış seçeneklerden bir değer seçme olanağ
|
||||
<Tab title="Kullanım">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Kullanıcıların metin girmelerine ve düzenlemelerine izin verir.
|
||||
<Tab title="Kullanım">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="Kullanıcı adı"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
},{
|
||||
@@ -81,12 +78,10 @@ Metni içeriğe göre otomatik olarak ayarlayan metin giriş bileşeni.
|
||||
<Tab title="Kullanım">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate fonksiyonu tetiklendi")}
|
||||
minRows={1}
|
||||
@@ -96,7 +91,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="Görev: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
+19
-18
@@ -6,9 +6,9 @@ title: 最佳实践
|
||||
|
||||
## 状态管理
|
||||
|
||||
React 和 Recoil 在代码库中处理状态管理。
|
||||
React 和 Jotai 在代码库中处理状态管理。
|
||||
|
||||
### 使用 `useRecoilState` 来存储状态
|
||||
### 使用 `useAtomState` 来存储状态
|
||||
|
||||
根据需要创建足够多的原子来存储你的状态,是一种良好实践。
|
||||
|
||||
@@ -19,13 +19,16 @@ React 和 Recoil 在代码库中处理状态管理。
|
||||
</Warning>
|
||||
|
||||
```tsx
|
||||
export const myAtomState = atom({
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
|
||||
export const myAtomState = createAtomState<string>({
|
||||
key: 'myAtomState',
|
||||
default: 'default value',
|
||||
defaultValue: 'default value',
|
||||
});
|
||||
|
||||
export const MyComponent = () => {
|
||||
const [myAtom, setMyAtom] = useRecoilState(myAtomState);
|
||||
const [myAtom, setMyAtom] = useAtomState(myAtomState);
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -42,7 +45,7 @@ export const MyComponent = () => {
|
||||
|
||||
避免使用 `useRef` 来存储状态。
|
||||
|
||||
如果想存储状态,应该使用 `useState` 或 `useRecoilState`。
|
||||
如果想存储状态,应该使用 `useState` 或 `useAtomState`。
|
||||
|
||||
如果您觉得需要通过使用 `useRef` 来防止一些再渲染,请了解[如何管理再渲染](#managing-re-renders)。
|
||||
|
||||
@@ -82,8 +85,8 @@ If you feel like you need to add a `useEffect` in your root component, you shoul
|
||||
// ❌ 不佳:即使数据未发生变化也会导致重新渲染,
|
||||
// 因为需要重新评估 useEffect
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -95,9 +98,7 @@ export const PageComponent = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
<PageComponent />
|
||||
);
|
||||
```
|
||||
|
||||
@@ -105,14 +106,14 @@ export const App = () => (
|
||||
// ✅ 良好:如果数据未发生变化,将不会导致重新渲染,
|
||||
// 因为 useEffect 会在另一个同级组件中重新评估
|
||||
export const PageComponent = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
|
||||
return <div>{data}</div>;
|
||||
};
|
||||
|
||||
export const PageData = () => {
|
||||
const [data, setData] = useRecoilState(dataState);
|
||||
const [someDependency] = useRecoilState(someDependencyState);
|
||||
const [data, setData] = useAtomState(dataState);
|
||||
const [someDependency] = useAtomState(someDependencyState);
|
||||
|
||||
useEffect(() => {
|
||||
if(someDependency !== data) {
|
||||
@@ -124,16 +125,16 @@ export const PageData = () => {
|
||||
};
|
||||
|
||||
export const App = () => (
|
||||
<RecoilRoot>
|
||||
<>
|
||||
<PageData />
|
||||
<PageComponent />
|
||||
</RecoilRoot>
|
||||
</>
|
||||
);
|
||||
```
|
||||
|
||||
### 使用 Recoil 状态族和 Recoil 选择器族
|
||||
### 使用 Jotai 状态族和 Jotai 选择器族
|
||||
|
||||
Recoil 状态族和选择器族是避免再渲染的好方法。
|
||||
Jotai 状态族和选择器族是避免再渲染的好方法。
|
||||
|
||||
当您需要存储项目列表时,它们很有用。
|
||||
|
||||
|
||||
+2
-2
@@ -82,9 +82,9 @@ module1
|
||||
|
||||
### 状态
|
||||
|
||||
包含状态管理逻辑。 [RecoilJS](https://recoiljs.org) 处理这部分。
|
||||
包含状态管理逻辑。 [Jotai](https://jotai.org) 处理这部分。
|
||||
|
||||
* 选择器:详情请参阅 [RecoilJS Selectors](https://recoiljs.org/docs/basic-tutorial/selectors)。
|
||||
* 选择器:派生原子(使用 `createAtomSelector`)从其他原子计算值,并自动进行记忆化。
|
||||
|
||||
React 内置状态管理仍然在组件内处理状态。
|
||||
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ npx nx run twenty-front:storybook:coverage # (needs yarn storybook:serve:dev to
|
||||
* [React](https://react.dev/)
|
||||
* [Apollo](https://www.apollographql.com/docs/)
|
||||
* [GraphQL 代码生成](https://the-guild.dev/graphql/codegen)
|
||||
* [Recoil](https://recoiljs.org/docs/introduction/core-concepts)
|
||||
* [Jotai](https://jotai.org/)
|
||||
* [TypeScript](https://www.typescriptlang.org/)
|
||||
|
||||
**测试**
|
||||
@@ -77,7 +77,7 @@ To avoid unnecessary [re-renders](/l/zh/developers/contribute/capabilities/front
|
||||
|
||||
### 状态管理
|
||||
|
||||
[Recoil](https://recoiljs.org/docs/introduction/core-concepts) 处理状态管理。
|
||||
[Jotai](https://jotai.org/) 处理状态管理。
|
||||
|
||||
查看[最佳实践](/l/zh/developers/contribute/capabilities/frontend-development/best-practices-front#state-management)以获取有关状态管理的更多信息。
|
||||
|
||||
|
||||
+3
-3
@@ -160,7 +160,7 @@ export enum PageHotkeyScope {
|
||||
}
|
||||
```
|
||||
|
||||
在内部,当前选择的范围存储在整个应用程序共享的 Recoil 状态中:
|
||||
在内部,当前选择的范围存储在整个应用程序共享的 Jotai 状态中:
|
||||
|
||||
```tsx
|
||||
export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
@@ -169,10 +169,10 @@ export const currentHotkeyScopeState = createState<HotkeyScope>({
|
||||
});
|
||||
```
|
||||
|
||||
但这个 Recoil 状态不应该手动处理! 我们将在下一节中学习如何使用它。
|
||||
但这个 Jotai 状态不应该手动处理! 我们将在下一节中学习如何使用它。
|
||||
|
||||
## 内部是如何运作的?
|
||||
|
||||
我们在 [react-hotkeys-hook](https://react-hotkeys-hook.vercel.app/docs/intro) 之上制作了一个薄包装,使其性能更高并避免不必要的重新渲染。
|
||||
|
||||
我们还创建了一个 Recoil 状态来处理快捷键范围状态,并使其在整个应用程序中可用。
|
||||
我们还创建了一个 Jotai 状态来处理快捷键范围状态,并使其在整个应用程序中可用。
|
||||
|
||||
@@ -14,7 +14,6 @@ image: /images/user-guide/github/github-header.png
|
||||
<Tab title="**用法**">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -27,14 +26,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ image: /images/user-guide/what-is-twenty/20.png
|
||||
<Tab title="**用法**">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -21,7 +20,6 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
@@ -32,7 +30,6 @@ export const MyComponent = () => {
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ image: /images/user-guide/notes/notes_header.png
|
||||
<Tab title="用法">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { TextInput } from "@/ui/input/components/TextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
@@ -29,7 +28,6 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<TextInput
|
||||
className
|
||||
label="用户名"
|
||||
@@ -40,7 +38,6 @@ export const MyComponent = () => {
|
||||
onKeyDown={handleKeyDown}
|
||||
RightIcon={null}
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
@@ -80,12 +77,10 @@ export const MyComponent = () => {
|
||||
<Tab title="用法">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { AutosizeTextInput } from "@/ui/input/components/AutosizeTextInput";
|
||||
|
||||
export const MyComponent = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<AutosizeTextInput
|
||||
onValidate={() => console.log("onValidate 函数已触发")}
|
||||
minRows={1}
|
||||
@@ -95,7 +90,6 @@ export const MyComponent = () => {
|
||||
buttonTitle
|
||||
value="任务: "
|
||||
/>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -13,7 +13,6 @@ A dropdown-based icon picker that allows users to select an icon from a list.
|
||||
<Tab title="Usage">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from "recoil";
|
||||
import React, { useState } from "react";
|
||||
import { IconPicker } from "@/ui/input/components/IconPicker";
|
||||
|
||||
@@ -26,14 +25,12 @@ export const MyComponent = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
<IconPicker
|
||||
disabled={false}
|
||||
onChange={handleIconChange}
|
||||
selectedIconKey={selectedIcon}
|
||||
variant="primary"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
@@ -12,7 +12,6 @@ Allows users to pick a value from a list of predefined options.
|
||||
<Tab title="Usage">
|
||||
|
||||
```jsx
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { IconTwentyStar } from 'twenty-ui/display';
|
||||
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@@ -20,18 +19,16 @@ import { Select } from '@/ui/input/components/Select';
|
||||
export const MyComponent = () => {
|
||||
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
label="Select an option"
|
||||
options={[
|
||||
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
|
||||
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
</RecoilRoot>
|
||||
<Select
|
||||
className
|
||||
disabled={false}
|
||||
label="Select an option"
|
||||
options={[
|
||||
{ value: 'option1', label: 'Option A', Icon: IconTwentyStar },
|
||||
{ value: 'option2', label: 'Option B', Icon: IconTwentyStar },
|
||||
]}
|
||||
value="option1"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user