一个轻量级的状态管理,具有React语法。
通过使用Reactter,您可以获得
功能
- 使用熟悉的语法,如UseState、UseEffect、UseContext、自定义hooks等。
- 创建自定义hooks以重用功能。
- 显著减少样板代码。
- 提高代码可读性。
- 单向数据流。
- 一种在应用程序中共享全局信息的简便方法。
用法
UseState
class AppContext extends ReactterContext {
// You can create the state here and add it to dependencies in
// constructor with listenHooks() */
final username = UseState<String>("");
AppContext(){
listenHooks([username]);
}
// We recommend to give the context to the state this way:
// With this, you no longer need to put it in listenHooks()
// which is cleaner */
late final firstName = UseState<String>("Leo", context: this);
late final lastName = UseState<String>("León", context: this);
}
您还可以创建任何其他类,并设置一个UseState属性来共享状态。
class Global {
static final currentUser = UseState<User?>(null);
}
但如果您需要响应式小部件,则需要使用ReactterContext或将此属性传递给ReactterContext。
请参阅自定义Hooks示例。
UseEffect
AppContext(){
UseEffect((){
userName.value = firstName + lastName;
}, [firstName, lastName]);
}
它应该在ReactterContext构造函数内部使用。
UseProvider和UseContext
UseProvider(
contexts: [
UseContext(
() => AppContext(),
init: true,
)
],
builder: (context, _) {
final appContext1 = context.of<AppContext>();
final appContext2 = context.of<AppContext>((ctx) => [ctx.userName]);
final appContext3 = context.ofStatic<AppContext>();
return Text(appContext1.username.value);
}
);
读取值
如上例所示,您可以通过三种不同的方式从上下文中读取值
context.of<AnyContext>():获取上下文的所有状态监听器。context.of<AnyContext>((ctx) => [ctx.anyState]):获取特定状态的监听器以进行重建,您可以根据需要使用任意数量。context.ofStatic<AppContext>():读取所有状态,但在更改时不会重建。
UseAsyncState
class AppContext extends ReactterContext {
late final userName =
UseAsyncState<String>("Init state", fillUsername, context: this);
Future<String> fillUsername() async {
final userFromApi = await getUserName();
return userFromApi;
}
// You should use anyAsyncState.resolve() to resolve the state
onClickGetUser(){
userName.resolve();
}
}
您可以在任何地方执行resolve()。
UseAsyncState.when
userContext.userName.when(
standby: (value) => Text("Standby: ${value}"),
loading: () => const CircularProgressIndicator(),
done: (value) => Text(value),
error: (error) => const Text("Unhandled exception: ${error}"),
)
<AnyAsyncState>.when接收四个函数,并始终返回一个widget,以根据状态的状态处理视图
standby:当状态具有初始值时。loading:当状态的请求正在检索值时。done:当请求完成时。error:如果请求中发生任何错误。
自定义Hooks
mixin UseCart on ReactterHook {
late final cart = UseState<Cart?>(null, context: this);
addProductToCart(Product product) {
final oldProducts = cart.value.products;
cart.value = cart.value?
.copyWith(products: [...oldProducts, product]);
}
}
您可以使用如下方式
class UserContext extends ReactterContext with UseCart {
final user = Global.currentUser;
UserContext() {
UseEffect(() {
cart.value = api.getUserCart(user.value?.id ?? 0);
}, [user]);
}
}
我们建议使用mixins来创建hooks,因为它们易于注入变量,但任何扩展ReactterHook的类都可以成为自定义hook。
ReactterContext上的生命周期方法
@override
awake() {}
@override
willMount() {}
@override
didMount() {}
@override
willUnmount() {}
所有ReacterContext都有这些生命周期方法
awake:在实例开始构建时执行。willMount:在依赖项widget挂载到树之前执行。didMount:在依赖项widget挂载到树之后执行。willUnmount:当widget从树中移除时执行。
路线图
我们也在创建一个文档页面,并制作YouTube教程。
我们希望为Reactter添加更多功能,以下是我们考虑的按优先级排序的
V2
- 测试
- 使
Reactter易于测试。
- 使
- 创建
- 可以选择从具有不同ID的上下文创建相同的实例,这对于列表widget非常有用,每个widget都将拥有自己的状态。
- 延迟UseContext
- 在需要之前不要初始化上下文。
- 子widget渲染可选
- 保存一个不会在状态更改时重新渲染的子widget。
- ReactterComponent
- 一个StatelessWidget,它将向所有widget公开
ReactterContext状态,而无需编写context.of<T>(),只需state.someProp。
- 一个StatelessWidget,它将向所有widget公开
- Equatable
- 在处理对象或列表时,移除状态中的
alwaysUpdate属性。
- 在处理对象或列表时,移除状态中的
ReactterComponents(新包)
- 按钮(几乎准备好发布)
- 应用栏
- 底部栏
- Snackbar
- 抽屉
- 浮动操作
- 模态框
- 输入框
警告
Reactter已刚离开开发阶段,您可以在生产环境中使用它,但用于小型应用程序时需谨慎,我们正在努力使其更具可测试性,并考虑状态管理的所有可能情况。API可能会因Roadmap而发生变化。
贡献
如果您想贡献,请随时在Reactter存储库中创建issue或pull request。
您可以
- 添加新的自定义hooks。
- 添加新的widget。
- 添加示例。
- 报告bug。
- 报告难以实现的情况。
- 报告不明确的错误。
- 报告不明确的文档。
- 撰写文章或制作视频,讲解如何使用Reactter。
任何想法都欢迎!