React மற்றும் React Native-க்கான ஸ்டேட் · 1.0
ஸ்டேட்டைப் பகிருங்கள்.ஒரே ஹூக்.முடிந்தது.
ஒரே வரியில் ஸ்டோரை அறிவித்து, Provider, action, reducer இல்லாமல் எந்தக் கம்போனென்டிலும் பயன்படுத்துங்கள். ஒரு கம்போனென்ட் தான் தேர்ந்தெடுத்த மதிப்பு மாறும்போது மட்டுமே மீண்டும் ரெண்டர் ஆகிறது; சேமிப்பு நீங்கள் முடிவு செய்யும்போது நடக்கிறது.
npm install @kkwaenggwari/restateநேரடி — உண்மையான restate ஸ்டோர்
useCart.set(cart => ({ ...cart, items: cart.items + 1, total: cart.total + 12 }))items, total மாறுகின்றன: மூன்று அட்டைகள் ரெண்டர் ஆகின்றன, பரிசு அட்டை அசையாமல் இருக்கிறது.
- எளிது0அமைப்புக்கான Provider, action, reducerஒரு மதிப்பை அறிவித்துப் பயன்படுத்துங்கள். முன்கூட்டியே எதையும் இணைக்க வேண்டியதில்லை.
- வேகம்11 → 1பதினொரு மாற்றங்கள், ஒரு எழுதுதல்autoSave ஒரு இடைவெளிக்குக் காத்திருக்கிறது; அதனால் பதினொரு வேக மாற்றங்கள் ஒரே எழுதுதலாகின்றன.
- நிலைத்தன்மை26வகையிடப்பட்ட பிழைக் குறியீடுகள்ஒவ்வொரு பிழையும் என்ன தவறு நடந்தது, எந்தப் பதிவுடன் தொடர்புடையது என்று சொல்கிறது.
01 — எளிது
அதே அம்சம், குறைவான கருத்துகள்.
ஒரே பணியின் நான்கு செயலாக்கங்கள் அருகருகே. எண்கள் இங்கே காட்டப்படும் குறியீட்டிலிருந்து வருகின்றன; இந்தத் தளம் build ஆகும்போது அளக்கப்படுகின்றன.
பகிரப்பட்ட எண்ணி
இரண்டு கம்போனென்ட்கள் ஒரே எண்ணைப் படித்துப் புதுப்பிக்கின்றன.
Redux Toolkit புதுப்பிப்புகளை slice-களாகவும் action-களாகவும் ஒழுங்கமைத்து, React context மூலம் வழங்கப்படும் ஸ்டோருக்கு அனுப்புகிறது. சிறந்த DevTools, பெரிய குழுக்களுக்குக் கண்டிப்பான, கணிக்கக்கூடிய புதுப்பிப்பு ஓட்டம்.
Zustand create() மூலம் ஸ்டோர் ஹூக்கை உருவாக்கி setState மூலம் மாற்றுகிறது. மிகச் சிறியது, நெகிழ்வானது; persistence, DevTools-க்கான middleware உடன்.
Jotai atom-களையும் பெறப்பட்ட atom-களையும் இணைக்கிறது, விருப்பப்பட்டால் Provider-க்குள். பல சிறிய ஸ்டேட் துண்டுகளுக்கு இடையே நுணுக்கமான சார்புகள்.
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useDispatch, useSelector } from 'react-redux';
const slice = createSlice({
name: 'count',
initialState: 0,
reducers: { increment: (count) => count + 1 },
});
const store = configureStore({
reducer: { count: slice.reducer },
});
function Counter() {
const count = useSelector((state) => state.count);
const dispatch = useDispatch();
return <button onClick={() => dispatch(slice.actions.increment())}>{count}</button>;
}
export default function App() {
return (
<Provider store={store}>
<Counter />
<Counter />
</Provider>
);
}import { create } from 'zustand';
const useCount = create(() => ({ count: 0 }));
const increment = () =>
useCount.setState((s) => ({
count: s.count + 1,
}));
function Counter() {
const count = useCount((s) => s.count);
return <button onClick={increment}>{count}</button>;
}
export default function App() {
return (
<>
<Counter />
<Counter />
</>
);
}import { atom, useAtom } from 'jotai';
const countAtom = atom(0);
function Counter() {
const [count, setCount] = useAtom(countAtom);
return <button onClick={() => setCount((n) => n + 1)}>{count}</button>;
}
export default function App() {
return (
<>
<Counter />
<Counter />
</>
);
}restate ஒரே அறிவிப்பு ஸ்டோரும் ஹூக்கும் ஆகும்.
import { restate } from '@kkwaenggwari/restate';
const useCount = restate(0);
function Counter() {
const count = useCount();
return <button onClick={() => useCount.set((n) => n + 1)}>{count}</button>;
}
export default function App() {
return (
<>
<Counter />
<Counter />
</>
);
}இந்தப் பணிக்கு Zustand, Jotai-உம் சிறியவை, Provider இல்லாதவை. சேமிப்பும் ஆவண வாரியான ஸ்டேட்டும் சேரும்போது வேறுபாடு வளர்கிறது.
புலத்தைத் தேர்ந்தெடுத்தல்
உரை மட்டும் மாறும்போது தலைப்புக் கம்போனென்ட் ரெண்டர் ஆகக்கூடாது.
Redux Toolkit புதுப்பிப்புகளை slice-களாகவும் action-களாகவும் ஒழுங்கமைத்து, React context மூலம் வழங்கப்படும் ஸ்டோருக்கு அனுப்புகிறது. சிறந்த DevTools, பெரிய குழுக்களுக்குக் கண்டிப்பான, கணிக்கக்கூடிய புதுப்பிப்பு ஓட்டம்.
Zustand create() மூலம் ஸ்டோர் ஹூக்கை உருவாக்கி setState மூலம் மாற்றுகிறது. மிகச் சிறியது, நெகிழ்வானது; persistence, DevTools-க்கான middleware உடன்.
Jotai atom-களையும் பெறப்பட்ட atom-களையும் இணைக்கிறது, விருப்பப்பட்டால் Provider-க்குள். பல சிறிய ஸ்டேட் துண்டுகளுக்கு இடையே நுணுக்கமான சார்புகள்.
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useSelector } from 'react-redux';
const article = createSlice({
name: 'article',
initialState: { title: 'Hello', body: '' },
reducers: {
editBody: (i) => {
i.body += '!';
},
editTitle: (i) => {
i.title += '!';
},
},
});
const store = configureStore({ reducer: article.reducer });
function Title() {
const title = useSelector((i) => i.title);
return <h3>{title}</h3>;
}
export default function App() {
return (
<Provider store={store}>
<Title />
<button onClick={() => store.dispatch(article.actions.editBody())}>body + !</button>
<button onClick={() => store.dispatch(article.actions.editTitle())}>title + !</button>
</Provider>
);
}import { create } from 'zustand';
const useArticle = create(() => ({ title: 'Hello', body: '' }));
function Title() {
const title = useArticle((i) => i.title);
return <h3>{title}</h3>;
}
export default function App() {
return (
<>
<Title />
<button
onClick={() =>
useArticle.setState((i) => ({
body: i.body + '!',
}))
}
>
body + !
</button>
<button
onClick={() =>
useArticle.setState((i) => ({
title: i.title + '!',
}))
}
>
title + !
</button>
</>
);
}import { atom, useAtomValue, useSetAtom } from 'jotai';
const articleAtom = atom({ title: 'Hello', body: '' });
const titleAtom = atom((get) => get(articleAtom).title);
function Title() {
const title = useAtomValue(titleAtom);
return <h3>{title}</h3>;
}
export default function App() {
const setArticle = useSetAtom(articleAtom);
return (
<>
<Title />
<button
onClick={() =>
setArticle((i) => ({
...i,
body: i.body + '!',
}))
}
>
body + !
</button>
<button
onClick={() =>
setArticle((i) => ({
...i,
title: i.title + '!',
}))
}
>
title + !
</button>
</>
);
}restate நீங்கள் ஏற்கெனவே பயன்படுத்தும் அதே ஹூக்குக்கு ஒரு selector கொடுங்கள்.
import { restate } from '@kkwaenggwari/restate';
const useArticle = restate({ title: 'Hello', body: '' });
function Title() {
const title = useArticle((i) => i.title);
return <h3>{title}</h3>;
}
export default function App() {
return (
<>
<Title />
<button
onClick={() =>
useArticle.set((i) => ({
...i,
body: i.body + '!',
}))
}
>
body + !
</button>
<button
onClick={() =>
useArticle.set((i) => ({
...i,
title: i.title + '!',
}))
}
>
title + !
</button>
</>
);
}இங்குள்ள எல்லாக் கருவிகளும் தேர்ந்தெடுக்க முடியும். restate தனி selector ஹூக் அல்லது பெறப்பட்ட atom-க்குப் பதிலாக அதே ஹூக் அழைப்பைப் பயன்படுத்துகிறது.
வரைவைச் சேமித்தல்
தொடக்கத்தில் சேமித்த வரைவை மீட்டெடுத்து, கிளிக் செய்யும்போது சேமித்து, சேமிக்கிறது, சேமிக்கப்படவில்லை, தோல்வி நிலைகளைக் காட்டுங்கள்.
Redux Toolkit புதுப்பிப்புகளை slice-களாகவும் action-களாகவும் ஒழுங்கமைத்து, React context மூலம் வழங்கப்படும் ஸ்டோருக்கு அனுப்புகிறது. சிறந்த DevTools, பெரிய குழுக்களுக்குக் கண்டிப்பான, கணிக்கக்கூடிய புதுப்பிப்பு ஓட்டம்.
Zustand create() மூலம் ஸ்டோர் ஹூக்கை உருவாக்கி setState மூலம் மாற்றுகிறது. மிகச் சிறியது, நெகிழ்வானது; persistence, DevTools-க்கான middleware உடன்.
Jotai atom-களையும் பெறப்பட்ட atom-களையும் இணைக்கிறது, விருப்பப்பட்டால் Provider-க்குள். பல சிறிய ஸ்டேட் துண்டுகளுக்கு இடையே நுணுக்கமான சார்புகள்.
import { useEffect, useState } from 'react';
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useSelector } from 'react-redux';
function openDraftDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('draft-example', 1);
let blocked = false;
request.onupgradeneeded = () => {
request.result.createObjectStore('drafts');
};
request.onblocked = () => {
blocked = true;
reject(new Error('Close other tabs to upgrade storage'));
};
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
if (blocked) {
db.close();
return;
}
db.onversionchange = () => db.close();
resolve(db);
};
});
}
async function storedDraft(mode, text) {
const db = await openDraftDB();
try {
return await new Promise((resolve, reject) => {
const tx = db.transaction('drafts', mode);
const store = tx.objectStore('drafts');
const request = mode === 'readonly' ? store.get('draft') : store.put(text, 'draft');
tx.oncomplete = () => resolve(request.result);
tx.onabort = () => reject(tx.error || new Error('Storage aborted'));
});
} finally {
db.close();
}
}
const draft = createSlice({
name: 'draft',
initialState: '',
reducers: { edit: (_, action) => action.payload },
});
const store = configureStore({ reducer: { draft: draft.reducer } });
const hydrated = storedDraft('readonly').then((saved) => {
if (saved === undefined) return;
if (typeof saved !== 'string') throw new Error('Invalid draft');
const value = saved;
store.dispatch(draft.actions.edit(value));
});
// Observe errors immediately, even before the component mounts.
hydrated.catch(() => {});
function DraftEditor() {
const text = useSelector((state) => state.draft);
const [ready, setReady] = useState(false);
const [saving, setSaving] = useState(false);
const [message, setMessage] = useState('Loading');
useEffect(() => {
let active = true;
hydrated.then(
() => {
if (active) {
setReady(true);
setMessage('Ready');
}
},
() => {
if (active) setMessage('Storage error');
},
);
return () => {
active = false;
};
}, []);
async function save() {
setSaving(true);
try {
await storedDraft('readwrite', store.getState().draft);
setMessage('Saved');
} catch {
setMessage('Save failed');
} finally {
setSaving(false);
}
}
return (
<>
<label>
Draft
<textarea
value={text}
disabled={!ready || saving}
onChange={(event) => {
const value = event.target.value;
store.dispatch(draft.actions.edit(value));
setMessage('Edited');
}}
/>
</label>
<output>{text}</output>
<button disabled={!ready || saving} onClick={save}>
Save
</button>
<p>{message}</p>
</>
);
}
export default function App() {
return (
<Provider store={store}>
<DraftEditor />
</Provider>
);
}import { useEffect, useState } from 'react';
import { create } from 'zustand';
function openDraftDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('draft-example', 1);
let blocked = false;
request.onupgradeneeded = () => {
request.result.createObjectStore('drafts');
};
request.onblocked = () => {
blocked = true;
reject(new Error('Close other tabs to upgrade storage'));
};
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
if (blocked) {
db.close();
return;
}
db.onversionchange = () => db.close();
resolve(db);
};
});
}
async function storedDraft(mode, text) {
const db = await openDraftDB();
try {
return await new Promise((resolve, reject) => {
const tx = db.transaction('drafts', mode);
const store = tx.objectStore('drafts');
const request = mode === 'readonly' ? store.get('draft') : store.put(text, 'draft');
tx.oncomplete = () => resolve(request.result);
tx.onabort = () => reject(tx.error || new Error('Storage aborted'));
});
} finally {
db.close();
}
}
const useDraft = create(() => ({ text: '' }));
const hydrated = storedDraft('readonly').then((saved) => {
if (saved === undefined) return;
if (typeof saved !== 'string') throw new Error('Invalid draft');
const value = saved;
useDraft.setState({ text: value });
});
// Observe errors immediately, even before the component mounts.
hydrated.catch(() => {});
function DraftEditor() {
const text = useDraft((state) => state.text);
const [ready, setReady] = useState(false);
const [saving, setSaving] = useState(false);
const [message, setMessage] = useState('Loading');
useEffect(() => {
let active = true;
hydrated.then(
() => {
if (active) {
setReady(true);
setMessage('Ready');
}
},
() => {
if (active) setMessage('Storage error');
},
);
return () => {
active = false;
};
}, []);
async function save() {
setSaving(true);
try {
await storedDraft('readwrite', useDraft.getState().text);
setMessage('Saved');
} catch {
setMessage('Save failed');
} finally {
setSaving(false);
}
}
return (
<>
<label>
Draft
<textarea
value={text}
disabled={!ready || saving}
onChange={(event) => {
const value = event.target.value;
useDraft.setState({ text: value });
setMessage('Edited');
}}
/>
</label>
<output>{text}</output>
<button disabled={!ready || saving} onClick={save}>
Save
</button>
<p>{message}</p>
</>
);
}
export default function App() {
return <DraftEditor />;
}import { useEffect, useState } from 'react';
import { atom, createStore, useAtomValue } from 'jotai';
function openDraftDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('draft-example', 1);
let blocked = false;
request.onupgradeneeded = () => {
request.result.createObjectStore('drafts');
};
request.onblocked = () => {
blocked = true;
reject(new Error('Close other tabs to upgrade storage'));
};
request.onerror = () => reject(request.error);
request.onsuccess = () => {
const db = request.result;
if (blocked) {
db.close();
return;
}
db.onversionchange = () => db.close();
resolve(db);
};
});
}
async function storedDraft(mode, text) {
const db = await openDraftDB();
try {
return await new Promise((resolve, reject) => {
const tx = db.transaction('drafts', mode);
const store = tx.objectStore('drafts');
const request = mode === 'readonly' ? store.get('draft') : store.put(text, 'draft');
tx.oncomplete = () => resolve(request.result);
tx.onabort = () => reject(tx.error || new Error('Storage aborted'));
});
} finally {
db.close();
}
}
const draftAtom = atom('');
const store = createStore();
const hydrated = storedDraft('readonly').then((saved) => {
if (saved === undefined) return;
if (typeof saved !== 'string') throw new Error('Invalid draft');
const value = saved;
store.set(draftAtom, value);
});
// Observe errors immediately, even before the component mounts.
hydrated.catch(() => {});
function DraftEditor() {
const text = useAtomValue(draftAtom, { store });
const [ready, setReady] = useState(false);
const [saving, setSaving] = useState(false);
const [message, setMessage] = useState('Loading');
useEffect(() => {
let active = true;
hydrated.then(
() => {
if (active) {
setReady(true);
setMessage('Ready');
}
},
() => {
if (active) setMessage('Storage error');
},
);
return () => {
active = false;
};
}, []);
async function save() {
setSaving(true);
try {
await storedDraft('readwrite', store.get(draftAtom));
setMessage('Saved');
} catch {
setMessage('Save failed');
} finally {
setSaving(false);
}
}
return (
<>
<label>
Draft
<textarea
value={text}
disabled={!ready || saving}
onChange={(event) => {
const value = event.target.value;
store.set(draftAtom, value);
setMessage('Edited');
}}
/>
</label>
<output>{text}</output>
<button disabled={!ready || saving} onClick={save}>
Save
</button>
<p>{message}</p>
</>
);
}
export default function App() {
return <DraftEditor />;
}restate persistedRestate தானாக மீட்டெடுக்கிறது; useStatus சேமிப்பு, சேமிக்கப்படாத மாற்றங்கள், பிழைகளைத் தெரிவிக்கிறது.
import { persistedRestate } from '@kkwaenggwari/restate';
const useDraft = persistedRestate('', {
key: 'draft',
validate: (value) => typeof value === 'string',
});
export default function App() {
const text = useDraft();
const { dirty, operation, error } = useDraft.useStatus();
const saving = operation === 'save';
const message = error ? 'Save failed' : saving ? 'Saving…' : dirty ? 'Edited' : 'Saved';
return (
<>
<label>
Draft
<textarea value={text} onChange={(event) => useDraft.set(event.target.value)} />
</label>
<output>{text}</output>
<button disabled={saving} onClick={() => useDraft.save().catch(() => {})}>
Save
</button>
<p>{message}</p>
</>
);
}மற்ற பதிப்புகள் அதே IndexedDB குறியீட்டைக் கையால் எழுதுகின்றன. அவற்றின் persistence middleware அல்லது சேமிப்பகக் கருவிகள் ஒரு அடாப்டருடன் அதைக் குறைக்கலாம்; அந்தக் குறியீடு இங்கே கணக்கில் இல்லை.
ஆவண வாரியான ஸ்டேட்
இரண்டு ஆவணங்கள் தனித்தனி ஸ்டேட்டை வைத்திருக்கின்றன; ஒன்றை மூடினால் அது விடுவிக்கப்படுகிறது.
Redux Toolkit புதுப்பிப்புகளை slice-களாகவும் action-களாகவும் ஒழுங்கமைத்து, React context மூலம் வழங்கப்படும் ஸ்டோருக்கு அனுப்புகிறது. சிறந்த DevTools, பெரிய குழுக்களுக்குக் கண்டிப்பான, கணிக்கக்கூடிய புதுப்பிப்பு ஓட்டம்.
Zustand create() மூலம் ஸ்டோர் ஹூக்கை உருவாக்கி setState மூலம் மாற்றுகிறது. மிகச் சிறியது, நெகிழ்வானது; persistence, DevTools-க்கான middleware உடன்.
Jotai atom-களையும் பெறப்பட்ட atom-களையும் இணைக்கிறது, விருப்பப்பட்டால் Provider-க்குள். பல சிறிய ஸ்டேட் துண்டுகளுக்கு இடையே நுணுக்கமான சார்புகள்.
import { useState } from 'react';
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useSelector } from 'react-redux';
const draft = createSlice({
name: 'draft',
initialState: '',
reducers: { edit: (_, action) => action.payload },
});
const selectionSlice = createSlice({
name: 'selection',
initialState: 0,
reducers: { next: (index) => index + 1 },
});
function createDocument() {
return {
store: configureStore({
reducer: {
draft: draft.reducer,
selection: selectionSlice.reducer,
},
}),
};
}
function Document({ doc, name }) {
const text = useSelector((state) => state.draft);
const selection = useSelector((state) => state.selection);
return (
<section>
<label>
{name}
<input
value={text}
onChange={(event) => doc.store.dispatch(draft.actions.edit(event.target.value))}
/>
</label>
<output>{text}</output>
<button onClick={() => doc.store.dispatch(selectionSlice.actions.next())}>
Selection: {selection}
</button>
</section>
);
}
function DocumentSlot({ name }) {
const [doc] = useState(createDocument);
return (
<Provider store={doc.store}>
<Document doc={doc} name={name} />
</Provider>
);
}
export default function App() {
const [leftOpen, setLeftOpen] = useState(true);
return (
<>
<button onClick={() => setLeftOpen((open) => !open)}>
{leftOpen ? 'Close left' : 'Open left'}
</button>
{leftOpen && <DocumentSlot name="Left" />}
<DocumentSlot name="Right" />
</>
);
}import { useState } from 'react';
import { useStore } from 'zustand';
import { createStore } from 'zustand/vanilla';
function createDocument() {
return {
draft: createStore(() => ({ text: '' })),
selection: createStore(() => ({ index: 0 })),
};
}
function Document({ doc, name }) {
const text = useStore(doc.draft, (state) => state.text);
const selection = useStore(doc.selection, (state) => state.index);
return (
<section>
<label>
{name}
<input
value={text}
onChange={(event) => doc.draft.setState({ text: event.target.value })}
/>
</label>
<output>{text}</output>
<button onClick={() => doc.selection.setState((s) => ({ index: s.index + 1 }))}>
Selection: {selection}
</button>
</section>
);
}
function DocumentSlot({ name }) {
const [doc] = useState(createDocument);
return <Document doc={doc} name={name} />;
}
export default function App() {
const [leftOpen, setLeftOpen] = useState(true);
return (
<>
<button onClick={() => setLeftOpen((open) => !open)}>
{leftOpen ? 'Close left' : 'Open left'}
</button>
{leftOpen && <DocumentSlot name="Left" />}
<DocumentSlot name="Right" />
</>
);
}import { useState } from 'react';
import { atom, createStore, useAtomValue } from 'jotai';
const draftAtom = atom('');
const selectionAtom = atom(0);
function createDocument() {
return { store: createStore() };
}
function Document({ doc, name }) {
const text = useAtomValue(draftAtom, { store: doc.store });
const selection = useAtomValue(selectionAtom, { store: doc.store });
return (
<section>
<label>
{name}
<input value={text} onChange={(event) => doc.store.set(draftAtom, event.target.value)} />
</label>
<output>{text}</output>
<button onClick={() => doc.store.set(selectionAtom, (n) => n + 1)}>
Selection: {selection}
</button>
</section>
);
}
function DocumentSlot({ name }) {
const [doc] = useState(createDocument);
return <Document doc={doc} name={name} />;
}
export default function App() {
const [leftOpen, setLeftOpen] = useState(true);
return (
<>
<button onClick={() => setLeftOpen((open) => !open)}>
{leftOpen ? 'Close left' : 'Open left'}
</button>
{leftOpen && <DocumentSlot name="Left" />}
<DocumentSlot name="Right" />
</>
);
}restate useRestateScope ஸ்டோர்களை உருவாக்கி, அன்மவுன்ட்டுக்குப் பிறகு அழிக்கிறது.
import { useState } from 'react';
import { restate, useRestateScope } from '@kkwaenggwari/restate';
function Document({ name }) {
const doc = useRestateScope((scope) => ({
useDraft: restate('', { scope }),
useSelection: restate(0, { scope }),
}));
const text = doc.useDraft();
const selection = doc.useSelection();
return (
<section>
<label>
{name}
<input value={text} onChange={(event) => doc.useDraft.set(event.target.value)} />
</label>
<output>{text}</output>
<button onClick={() => doc.useSelection.set((n) => n + 1)}>Selection: {selection}</button>
</section>
);
}
export default function App() {
const [leftOpen, setLeftOpen] = useState(true);
return (
<>
<button onClick={() => setLeftOpen((open) => !open)}>
{leftOpen ? 'Close left' : 'Open left'}
</button>
{leftOpen && <Document name="Left" />}
<Document name="Right" />
</>
);
}Jotai-இல் Provider அல்லது store-உம், Zustand-இல் vanilla store-களும் ஸ்டேட்டைத் தனிமைப்படுத்தலாம்; அவற்றை நீங்களே உருவாக்கி இணைக்கிறீர்கள்.
இந்த எண்கள் எப்படிக் கணக்கிடப்படுகின்றன
காட்டப்படும் குறியீட்டின் காலியல்லாத வரிகளும், ஒவ்வொரு ஸ்டேட் லைப்ரரியிலிருந்தும் import செய்யப்பட்ட பெயர்களும் (React import-கள் கணக்கில் இல்லை). ஒவ்வொரு பதிப்பும் அதே UI-ஐ அதே சேமிப்பகம், அதே ஏற்றுதல் மற்றும் பிழை நிலைகளுடன் ரெண்டர் செய்கிறது. restate எடுத்துக்காட்டுகள் ஆப்பின் நுழைவுப் புள்ளியில் await restateManager.ready இருப்பதாகக் கருதுகின்றன. மூலங்கள் ஒவ்வொரு திட்டத்தின் அதிகாரப்பூர்வ ஆவணங்களுடன் சரிபார்க்கப்பட்டவை:
- Redux Toolkit — Redux Toolkit · Quick Start, React Redux · useSelector, Redux Toolkit · configureStore. தணிக்கை செய்யக்கூடிய ஒரே action பதிவும் பெரிய middleware சூழலும் மிக முக்கியமானால் இதைத் தேர்ந்தெடுங்கள்
- Zustand — Zustand · Introduction, Zustand · persist. மிகச் சிறிய மையத்தை விரும்பி, middleware-ஐ நீங்களே சேர்க்க விரும்பினால் இதைத் தேர்ந்தெடுங்கள்
- Jotai — Jotai · atom, Jotai · Storage, Jotai · Provider. உங்கள் ஸ்டேட் இயல்பாகவே சிறிய பெறப்பட்ட மதிப்புகளின் வரைபடமாக இருந்தால் இதைத் தேர்ந்தெடுங்கள்
02 — வேகம்
மாறியதை மட்டும் ரெண்டர் செய்யுங்கள். ஒருமுறை எழுதுங்கள்.
இரு பலகைகளும் உங்கள் உலாவியில் உண்மையான restate தொகுப்பை இயக்குகின்றன. கிளிக் செய்து, தட்டச்சு செய்து, எண்ணிக்கைகளைக் கவனியுங்கள்.
ரெண்டர் வரைபடம்
அதே நான்கு புலங்கள், இரண்டு வழிகளில் படிக்கப்படுகின்றன. ஒரு புலத்தை மாற்றி ரெண்டர்களை எண்ணுங்கள்.
- பெயர்
- தீம்
- எண்ணி
- வரைவு
- பெயர்
- தீம்
- எண்ணி
- வரைவு
ஒருங்கிணைந்த எழுதுதல்கள்
autoSave தட்டச்சில் இடைவெளிக்குக் காத்திருந்து ஒருமுறை எழுதுகிறது. தொடர்ச்சியான save() அழைப்புகள் வரிசையில் உள்ள ஒரே எழுதுதலைப் பகிர்கின்றன.
persistedRestate('', { key: 'note', autoSave: { delayMs: 400 } });எண்கள் இந்தப் பக்கத்தில் உண்மையான React ரெண்டர்களிலிருந்தும் எழுதுதல்களை எண்ணும் சேமிப்பக அடாப்டரிலிருந்தும் வருகின்றன. மற்ற லைப்ரரிகளும் மதிப்புகளைத் தேர்ந்தெடுக்கலாம்; இங்கே தேர்ந்தெடுப்பது படிக்கும் ஒரு வழி மட்டுமே.
03 — நிலைத்தன்மை
சேமிப்பகம் தோல்வியடைந்தாலும் உங்கள் தரவு அப்படியே இருக்கும்.
ஸ்டேட் சேமிக்கும் நேரத்திலேயே இழக்கப்படுகிறது: மெதுவான டிஸ்க், தடுக்கப்பட்ட சேமிப்பகம், மூடப்பட்ட தாவல்கள். இவை restate 1.0-இன் உத்தரவாதங்கள், அறிவுரைகள் அல்ல.
- 01
சேமிப்புகள் வரிசையாக நடக்கின்றன
ஒவ்வொரு ஸ்டோரும் சேமிப்பகச் செயல்களை ஒவ்வொன்றாகச் செய்கிறது; அதனால் மெதுவான சேமிப்பு ஒருபோதும் பழைய மதிப்பு புதியதை மேலெழுத விடாது.
save() · restore() - 02
நிலுவையிலுள்ள சேமிப்பு சமீபத்திய மதிப்பை எடுக்கிறது
இன்னொரு சேமிப்பு வரிசையில் இருக்கும்போது save()-ஐ அழைத்தால், கூடுதல் எழுதுதல்களைக் குவிக்காமல் அதனுடன் சேர்ந்துகொள்கிறது.
save(): Promise<T> - 03
படிக்கப்படாத பதிவுகள் ஒருபோதும் தவறுதலாக மாற்றப்படுவதில்லை
ஒரு பதிவு ஏறவில்லை என்றால், autoSave-உம் மொத்தச் சேமிப்புகளும் அதைத் தொடாமல் LOAD_FAILED என்று தெரிவிக்கின்றன. வெளிப்படையான save() மட்டுமே அதை மாற்ற முடியும்.
LOAD_FAILED - 04
அன்மவுன்ட் ஆன பிறகும் சேமிப்பு முடிகிறது
அன்மவுன்ட் ஆகும் முன் கோரப்பட்ட சேமிப்புகள் முடிகின்றன. அழிக்கப்பட்ட ஸ்டோரில் பின்னர் வரும் எழுதுதல்கள், அன்மவுன்ட்டுக்குப் பிறகான React ஸ்டேட் போலவே புறக்கணிக்கப்படுகின்றன.
useRestateScope - 05
சேமிப்பகம் இல்லையா? ஆப் இருந்தும் தொடங்கும்
சர்வர் ரெண்டரிங்கின்போதோ சேமிப்பகம் தடுக்கப்படும்போதோ, ஸ்டோர்கள் நினைவகத்தில் தொடர்ந்து இயங்கி, சேமிப்பகம் கிடைக்கவில்லை என்று தெரிவிக்கின்றன.
status().available - 06
பிழைகள் என்ன, எங்கே என்று சொல்கின்றன
ஒவ்வொரு restate பிழையிலும் வகையிடப்பட்ட குறியீடும் அதன் பதிவின் key-உம் உள்ளன; அதனால் சரியான செய்தியைக் காட்டலாம்.
error.code · error.key
உங்கள் ஆப்புடன் சேர்ந்து வளர்கிறது
அறிவிப்பை மாற்றுங்கள். கம்போனென்ட்களை அப்படியே வையுங்கள்.
சேமிப்பு, தானியங்கிச் சேமிப்பு, சரிபார்ப்பு ஆகியவை ஒரே ஸ்டோரின் விருப்பங்கள். வலது பக்கக் கம்போனென்ட் ஒருபோதும் மாறுவதில்லை.
நினைவகம்
நினைவகத்தில் பகிரப்பட்ட மதிப்பு.
import { restate } from '@kkwaenggwari/restate'; export const useDraft = restate('');சேமிக்கப்பட்டது
தானாக மீட்டெடுக்கப்படும்; save()-ஐ அழைக்கும்போது எழுதப்படும்.
import { persistedRestate } from '@kkwaenggwari/restate'; export const useDraft = persistedRestate('', { key: 'draft' });தானியங்கிச் சேமிப்பு
தட்டச்சில் 500 ms இடைவெளிக்குப் பிறகு ஒருமுறை எழுதப்படும்.
import { persistedRestate } from '@kkwaenggwari/restate'; export const useDraft = persistedRestate('', { key: 'draft', autoSave: { delayMs: 500 }, });சரிபார்ப்புடன்
பழைய பதிவுகள் பயன்படுத்தும் முன் மாற்றப்பட்டுச் சரிபார்க்கப்படுகின்றன.
import { persistedRestate } from '@kkwaenggwari/restate'; export const useDraft = persistedRestate('', { key: 'draft', autoSave: { delayMs: 500 }, version: 2, migrate: (value) => String(value ?? ''), validate: (value) => typeof value === 'string', });
கம்போனென்ட் — ஒவ்வொரு படியிலும் அதே
function Editor() {
const text = useDraft();
return <textarea value={text} onChange={(event) => useDraft.set(event.target.value)} />;
}React இயங்கும் எல்லா இடத்திலும் இயங்கும்
ஒவ்வொரு React சூழலுக்கும் ஒரே தொகுப்பு.
react >=16.8.0React
React 16.8 மற்றும் புதிய பதிப்புகளுடன், உலாவியிலும் சர்வர் ரெண்டரிங்கின்போதும் இயங்கும்.
react-native-mmkv >=2.0.0React Native
அதே import-கள். react-native-mmkv-ஐ நிறுவியவுடன் சேமிப்பு MMKV-ஐப் பயன்படுத்தும்.
SSRசர்வர் ரெண்டரிங்
கம்போனென்ட் ஸ்டோர்கள் props-இலிருந்து சர்வர் ஸ்னாப்ஷாட்டை எடுத்து, hydration-க்குப் பிறகு ஏற்றத் தொடங்குகின்றன.
index.d.tsTypeScript
அறிவிப்புகள் உடன் வருகின்றன. செலக்டர்கள், நிலைப் புலங்கள், பிழைக் குறியீடுகள் வகையிடப்பட்டவை.
தொடக்கம்
ஒரு நிமிடத்தில் உங்கள் முதல் பகிரப்பட்ட ஸ்டேட்.
நிறுவுங்கள், அறிவியுங்கள், பயன்படுத்துங்கள். ஆப்புக்குத் தேவைப்படும்போது சேமிப்பைச் சேருங்கள்.
- 01நிறுவுதல்
npm install @kkwaenggwari/restate - 02ஒரு ஸ்டோரை அறிவியுங்கள்
export const useCart = restate({ items: 0, total: 0 }); - 03எந்தக் கம்போனென்டிலும் படியுங்கள்
const items = useCart((cart) => cart.items);
KKWAENGGWARI