restate / v1.0.0

State thuộc về component

Cho mỗi tài liệu, hộp thoại hoặc yêu cầu các store riêng, được tạo cùng component và giải phóng sau khi nó unmount.

Trên trang nàyuseRestateScopeQuy tắc cho factoryGiá trị ban đầu từ propsRender phía máy chủChờ dữ liệu đã lưu của tài liệuThử ngayChủ sở hữu bên ngoài React

useRestateScope

Factory khai báo store và trả về chúng. restate giữ kết quả qua các lần render và hủy scope sau khi component unmount. Không cần viết hàm đóng hay effect dọn dẹp nào.

Hai phần tử Document có state độc lập. Để chia sẻ một tài liệu với các con, hãy truyền các hook trả về qua props hoặc context của riêng bạn.

JavaScript / JSX
import { restate, useRestateScope } from '@kkwaenggwari/restate';

function Document() {
  const { useDraft, useSelection } = useRestateScope((scope) => ({
    useDraft: restate('', { scope }),
    useSelection: restate(0, { scope }),
  }));
  const text = useDraft();
  const selection = useSelection();

  return (
    <section>
      <input value={text} onChange={(event) => useDraft.set(event.target.value)} />
      <button onClick={() => useSelection.set((n) => n + 1)}>Selection: {selection}</button>
    </section>
  );
}

Quy tắc cho factory

React có thể gọi factory nhiều lần và bỏ kết quả, nên hãy giữ nó đồng bộ và thuần.

  • Khai báo store trong factory; gọi các hook trả về ở cấp cao nhất của component.
  • Props ban đầu được đọc một lần, như trong hàm khởi tạo của useState.
  • Đặt key cho component khi một tài liệu khác cần state mới.
  • Không có factory, useRestateScope() trả về một scope ổn định cho các store bạn tạo sau trong effect hoặc handler.

Giá trị ban đầu từ props

Dùng props làm giá trị ban đầu, và key của React để bắt đầu lại với tài liệu khác.

JavaScript / JSX
function Editor({ document }) {
  // The initial value is captured once, like a useState initializer.
  const useTitle = useRestateScope((scope) => restate(document.title, { scope }));
  const title = useTitle();
  return <input value={title} onChange={(event) => useTitle.set(event.target.value)} />;
}

// A different document gets fresh state.
<Editor key={document.id} document={document} />;

Render phía máy chủ

Tải dữ liệu trong route máy chủ và truyền nó dưới dạng prop. Giá trị ban đầu cũng là snapshot máy chủ. Trong Next.js App Router, hook này nằm trong Client Component, vốn vẫn được render trên máy chủ.

JavaScript / JSX
'use client';

import { restate, useRestateScope } from '@kkwaenggwari/restate';

export default function Profile({ user }) {
  const useProfile = useRestateScope((scope) => restate(user, { scope }));
  const profile = useProfile();
  return <p>{profile.name}</p>;
}

Chờ dữ liệu đã lưu của tài liệu

Store được lưu trong scope bắt đầu khôi phục khi component được commit ở phía client và không thuộc restateManager.ready toàn cục. Hãy chờ manager.ready riêng của scope bên trong ranh giới tải.

JavaScript / JSX
import { useEffect, useState } from 'react';
import { persistedRestate, useRestateScope } from '@kkwaenggwari/restate';

function Document({ documentId }) {
  const { manager, useDraft } = useRestateScope((scope) => ({
    manager: scope.manager,
    useDraft: persistedRestate('', { scope, namespace: 'documents', key: documentId }),
  }));
  const [state, setState] = useState('loading');

  useEffect(() => {
    let active = true;
    manager.ready.then(
      () => active && setState('ready'),
      () => active && setState('error'),
    );
    return () => {
      active = false;
    };
  }, [manager]);

  if (state === 'error') return <p>Could not load this document.</p>;
  if (state === 'loading') return <p>Loading document…</p>;
  return <Editor useDraft={useDraft} />;
}

Thử ngay

Mở và đóng tài liệu, rồi xem state của chúng bắt đầu lại thế nào.

Đang chuẩn bị ví dụ…

Chủ sở hữu bên ngoài React

Khi state thuộc về một service hoặc yêu cầu phía máy chủ, hãy tự tạo scope và gọi destroy() khi xong. Hủy scope không bao giờ xóa bản ghi đã lưu.

JavaScript / JSX
import { createRestateScope, persistedRestate } from '@kkwaenggwari/restate';

export function createDocument(documentId) {
  const scope = createRestateScope();
  const useDraft = persistedRestate('', {
    scope,
    namespace: 'documents',
    key: documentId,
  });
  return {
    useDraft,
    manager: scope.manager,
    save: () => scope.manager.saveAll(),
    destroy: () => scope.destroy(),
  };
}

Tìm trong tài liệu

Tìm trong tiêu đề, mô tả và nội dung của mọi hướng dẫn.