SuperNode
App

Hooks 与 Context

App 页面中的状态、副作用与共享值。

在函数组件顶层按固定顺序调用 Hooks,并从 supernode/app 导入。Hooks 只在 app.show() 中运行;在其他地方调用(包括小组件视图)会抛出异常。

useState

useState(initial) 返回 [value, setValue]。initial 可以是值,也可以是只执行一次、用于生成初值的函数。setValue 接受下一个值,或更新函数 (current) => next。相等的值(Object.is)会跳过重新渲染;setter 的引用保持稳定。

import { app } from "supernode";
import { Column, Text, TextField, useState } from "supernode/app";

function Profile() {
  const [name, setName] = useState(() => "SuperNode");
  return (
    <Column spacing={12}>
      <Text fontSize={24}>你好,{name}</Text>
      <TextField value={name} placeholder="姓名" onValueChange={setName} />
    </Column>
  );
}

await app.show({ views: <Profile /> });

useReducer

useReducer(reducer, initialArg, init?) 返回 [state, dispatch],通过 reducer 更新状态。提供 init 时,初始状态为 init(initialArg),且该函数只运行一次。dispatch 的引用保持稳定,并始终使用最新的 reducer 处理 action。

import { app } from "supernode";
import { Column, Text, TextField, useReducer } from "supernode/app";

function reducer(state: { name: string }, name: string) {
  return { name };
}

function Form() {
  const [state, dispatch] = useReducer(reducer, "SuperNode", name => ({ name }));
  return (
    <Column spacing={12}>
      <Text fontSize={24}>你好,{state.name}</Text>
      <TextField value={state.name} placeholder="姓名" onValueChange={dispatch} />
    </Column>
  );
}

await app.show({ views: <Form /> });

useEffect

useEffect(setup, dependencies?) 在原生页面挂载或更新后执行 setup。setup 可返回同步 cleanup。[] 表示每次挂载执行一次;省略依赖列表则每次渲染后都执行。cleanup 会在下一次 setup 之前以及页面关闭时运行。不支持异步 setup。

import { app } from "supernode";
import { Text, useEffect, useState } from "supernode/app";

function Clock() {
  const [seconds, setSeconds] = useState(0);
  useEffect(() => {
    const timer = setInterval(() => setSeconds(value => value + 1), 1000);
    return () => clearInterval(timer);
  }, []);
  return <Text>{seconds} 秒</Text>;
}

await app.show({ views: <Clock /> });

useMemo

useMemo(calculate, dependencies?) 在依赖值保持相等时复用 calculate 的结果;某个依赖变化时重新计算。[] 表示每次挂载计算一次;省略依赖列表则每次渲染都计算。依赖列表的长度在多次渲染中必须保持一致。

import { app } from "supernode";
import { Column, Text, TextField, useMemo, useState } from "supernode/app";

function Preview() {
  const [title, setTitle] = useState("SuperNode");
  const label = useMemo(() => title.trim() || "未命名", [title]);
  return (
    <Column spacing={12}>
      <Text fontSize={24}>{label}</Text>
      <TextField value={title} placeholder="标题" onValueChange={setTitle} />
    </Column>
  );
}

await app.show({ views: <Preview /> });

useCallback

useCallback(callback, dependencies?) 在依赖保持相等时复用同一个函数实例。适合作为子组件或 effect 的依赖。[] 会在组件生命周期内保留该函数;省略依赖列表则每次渲染都返回新函数。

import { app } from "supernode";
import { Column, Text, TextField, useCallback, useState } from "supernode/app";

function Profile() {
  const [name, setName] = useState("");
  const onValueChange = useCallback((value: string) => setName(value.trim()), []);
  return (
    <Column spacing={12}>
      <Text>你好,{name || "访客"}</Text>
      <TextField value={name} placeholder="姓名" onValueChange={onValueChange} />
    </Column>
  );
}

await app.show({ views: <Profile /> });

useContext

createContext(defaultValue) 创建带 Provider 与 Consumer 的 context。useContext(context) 读取最近的 Provider 值;若不存在则使用默认值。Consumer 的子节点必须是函数。

import { app } from "supernode";
import { createContext, Text, useContext } from "supernode/app";

const Greeting = createContext("你好");

function Message() {
  const greeting = useContext(Greeting);
  return <Text>{greeting}</Text>;
}

await app.show({
  views: (
    <Greeting.Provider value="欢迎">
      <Message />
    </Greeting.Provider>
  ),
});

使用规则

状态更新会批量调度渲染。保持渲染过程纯净,在 effect cleanup 中释放外部资源。组件外调用 Hook、改变 Hook 调用顺序、卸载后更新状态都会报错。

小组件只渲染一次,不支持 Hooks 与 Context,详见 Widget。

本页目录