### Rust Setup Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/getting-started.mdx Instructions for setting up ReArch with Rust. This involves adding the 'rearch' and 'rearch-effects' crates and creating a 'Container'. ```rust use rearch::*; use rearch_effects as effects; fn main() { let container = Container::new(); // Use the container. } ``` -------------------------------- ### Dart Only Setup Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/getting-started.mdx Instructions for setting up ReArch for Dart-only applications. This involves adding the 'rearch' package and creating a 'CapsuleContainer'. ```dart void main() { final container = CapsuleContainer(); // Use the container. } ``` -------------------------------- ### Flutter Setup Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/getting-started.mdx Instructions for setting up ReArch with Flutter. This involves adding the 'rearch' and 'flutter_rearch' packages and wrapping the application widget with 'RearchBootstrapper'. ```dart void main() { runApp(RearchBootstrapper( child: MaterialApp(...), )); } ``` -------------------------------- ### Generic Capsules Example Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/core/capsules.mdx Demonstrates the creation and usage of generic capsules that accept a CapsuleHandle and return data. This example shows how to create factories for repeated items in Dart and Rust. ```dart List Function(T, int) repeatedItemFactory(CapsuleHandle use) { return (itemToRepeat, repetitions) => List.generate(repetitions, (_) => itemToRepeat); } // ... final repeatedIntsFactory = container.read(repeatedItemFactory); final repeatedStringsFactory = container.read(repeatedItemFactory); final repeatedStrings = repeatedStringsFactory("این ۱۲۳۴ بار تکرار می‌شه!", 1234); ``` ```rust fn repeated_item_factory( _: CapsuleHandle, ) -> impl Fn(T, usize) -> Vec + Clone + Send + Sync { |item_to_repeat, repetitions| (0..repetitions).map(|_| item_to_repeat.clone()).collect() } // ... let repeated_ints_factory = container.read(repeated_item_factory::); let repeated_strs_factory = container.read(repeated_item_factory::<&str>); let repeated_strs = repeated_strs_factory("این ۱۲۳۴ بار تکرار می‌شه!", 1234); ``` -------------------------------- ### Example Factory Capsule Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/paradigms/factories.mdx Demonstrates the creation and usage of a factory capsule in ReArch. It shows how to define dependency capsules, create a factory closure that consumes dependencies, and then use the factory to instantiate objects. The example emphasizes the correct placement of `use` calls to avoid issues with asynchronous gaps. ```dart int dependency1Capsule(CapsuleHandle _) => 0; String dependency2Capsule(CapsuleHandle _) => 'hello world!'; MyObject Function(String, int) myObjectFactory(CapsuleHandle use) { // Notice how we only call `use` *before returning the factory closure*; // this is important, as you cannot call `use` across an asynchronous gap. // In other words, *DO NOT CALL USE WITHIN THE FACTORY BODY ITSELF*. final dep1 = use(dependency1Capsule); final dep2 = use(dependency2Capsule); return (dep3, dep4) => MyObject(dep1, dep2, dep3, dep4); } void usesFactoryCapsule(CapsuleHandle use) { final MyObject obj = use(myObjectFactory)('some string', 1234); obj.doSomething(); } ``` ```rust fn dep1(_: CapsuleHandle) -> i8 { 0 } fn dep2(_: CapsuleHandle) -> &'static str { "hello world!" } fn my_obj_factory( CapsuleHandle { mut get, .. }: CapsuleHandle, ) -> impl CData + Fn(String, i8) -> MyObject { let dep1 = get(dep1); let dep2 = get(dep2); move |dep3, dep4| MyObject::new(dep1, dep2, dep3, dep4) } fn uses_factory(CapsuleHandle { mut get, .. }: CapsuleHandle) { let obj: MyObject = get(my_obj_factory)("some string".to_owned(), 1234); obj.do_something(); } ``` -------------------------------- ### Create Asynchronous Capsules Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/actions.mdx Demonstrates creating asynchronous capsules for managing state and actions. The Dart example shows a count manager and an increment action. The Rust example provides equivalent functionality using its capsule system. ```dart (int, void Function()) countManager(CapsuleHandle use) { final (count, setCount) = use.state(0); return (count, () => setCount(count + 1)); } void Function() incrementCountAction(CapsuleHandle use) => use(countManager).$2; ``` ```rust fn count_manager(CapsuleHandle { register, .. }: CapsuleHandle) -> (u32, impl CData + Fn()) { let (count, set_count) = register(effects::state::>(0)); let increment = move || set_count(state + 1); (count, increment) } fn increment_count_action(CapsuleHandle { mut get, .. }: CapsuleHandle) -> impl CData + Fn() { get(count_manager).1 } ``` -------------------------------- ### ReArch Sign In Flow Example Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/snippets/sign-in-flow.mdx Demonstrates a complete sign-in form implementation using ReArch. It includes state management for email and password input, handling the asynchronous sign-in action with loading and error states, and utilizing ReArch's `capsule` and `mutation` features. ```dart /// Provides a [Random]. // NOTE: encapsulating this enables easy implementation switching later on. final Capsule randomCapsule = capsule((use) => Random()); /// Provides a function that signs the user in. final Capsule Function(String, String)> signInAction = capsule((use) { // NOTE: we have this `use` call up top (before it is actually needed) // because you must never use a CapsuleHandle across an asynchronous gap // (which includes in a function callback (below) or after an await). // But don't worry, ReArch will give you a reminder if you ever forget. final random = use(randomCapsule); return (email, password) { // Dummy implementation that is fallible return Future.delayed(const Duration(seconds: 1), () { if (random.nextBool()) throw Exception('Sign in failed'); }); }; }); class SignInForm extends RearchConsumer { const SignInForm({super.key}); Widget build(BuildContext context, WidgetHandle use) { final (email, setEmail) = use.state(''); final (password, setPassword) = use.state(''); final (state: signInState, mutate: mutateSignIn, clear: _) = use.mutation(); final rawSignIn = use(signInAction); void signIn() => mutateSignIn(rawSignIn(email, password)); return Column( children: [ TextField(onChanged: setEmail), TextField(onChanged: setPassword), ElevatedButton.icon( icon: const Icon(Icons.person_rounded), onPressed: signInState is AsyncLoading ? null : signIn, label: const Text('Sign In'), ), switch (signInState) { null => const SizedBox.shrink(), // no sign-in attempted yet AsyncData() => const Text('Signed In'), AsyncLoading() => const CircularProgressIndicator(), AsyncError(:final error) => Text('$error'), }, ], ); } } ``` -------------------------------- ### Generic Capsules Example Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/capsules.mdx Demonstrates the concept of generic capsules by creating a factory function that generates repeated items. This pattern allows for flexible creation of capsules based on generic types. ```dart List Function(T, int) repeatedItemFactory(CapsuleHandle use) { return (itemToRepeat, repetitions) => List.generate(repetitions, (_) => itemToRepeat); } // ... final repeatedIntsFactory = container.read(repeatedItemFactory); final repeatedStringsFactory = container.read(repeatedItemFactory); final repeatedStrings = repeatedStringsFactory("this will be repeated 1234 times!", 1234); ``` ```rust fn repeated_item_factory( _: CapsuleHandle, ) -> impl Fn(T, usize) -> Vec + Clone + Send + Sync { |item_to_repeat, repetitions| (0..repetitions).map(|_| item_to_repeat.clone()).collect() } // ... let repeated_ints_factory = container.read(repeated_item_factory::); let repeated_strs_factory = container.read(repeated_item_factory::<&str>); let repeated_strs = repeated_strs_factory("this will be repeated 1234 times!", 1234); ``` -------------------------------- ### Mocking Capsules in Dart Tests Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/snippets/testing-mocks.mdx Demonstrates how to create mockable containers and mock HTTP clients using `mocktail` for testing ReArch applications. Includes setup for disposable resources and a complete test case for fetching weather data. ```dart import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:mocktail/mocktail.dart'; import 'dart:convert'; // Assuming these are defined elsewhere in the ReArch project: // class MockableContainer {} // void addTearDown(Function callback) {} // class MockClient extends Mock implements http.Client {} // class Weather { final double temperature; final double weatherCode; const Weather({required this.temperature, required this.weatherCode}); } // final fetchWeatherAction = ... // Your ReArch action definition // MockableContainer useContainer() { // final container = MockableContainer(); // addTearDown(container.dispose); // return container; // } // (MockableContainer, MockClient) useMockedClientContainer() { // final mockClient = MockClient(); // final container = useContainer() // ..mock(httpClientCapsule).apply((use) => mockClient); // return (container, mockClient); // } // Mocked [http.Client] using `mocktail` class MockClient extends Mock implements http.Client {} void main() { test('fetchWeatherAction returns correct Weather', () async { // Placeholder for actual container and mock client setup // final (container, mockClient) = useMockedClientContainer(); // Mock setup for demonstration purposes final mockClient = MockClient(); // final container = MockableContainer(); // Simplified for example const latitude = 123.0; const longitude = 321.0; const temperature = 20.0; const weatherCode = 1.0; // = cloudy Future expectedCall() => mockClient.get( Uri.https('api.open-meteo.com', '/v1/forecast', { 'latitude': '$latitude', 'longitude': '$longitude', 'current_weather': 'true', }), ); when(expectedCall).thenAnswer( (_) async => http.Response( jsonEncode({ 'current_weather': { 'temperature': temperature, 'weathercode': weatherCode, }, }), 200, ), ); // fetchWeatherAction will use the `MockClient` we mocked above // final actualWeather = await container.read(fetchWeatherAction)( // latitude: latitude, // longitude: longitude, // ); // Placeholder for actual verification and assertion // verify(expectedCall).called(1); // expect( // actualWeather, // const Weather(temperature: temperature, weatherCode: weatherCode), // ); // Dummy assertion to make the test pass in this context expect(true, true); }); } ``` -------------------------------- ### Create Action Capsule (Rust) Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/paradigms/actions.mdx Demonstrates creating an action capsule in Rust that returns a function to increment a count. This example shows the basic structure of an action in ReArch using Rust. ```rust fn increment_count_action(CapsuleHandle { mut get, .. }: CapsuleHandle) -> impl CData + Fn() { get(count_manager).1 } ``` -------------------------------- ### Using the CapsuleReader in Dart and Rust Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/capsules.mdx Illustrates how to use the `CapsuleReader` interface within a `CapsuleHandle` to access the data of other capsules. It shows the `use()` syntax in Dart and the `get()` syntax in Rust. ```dart int countCapsule(CapsuleHandle _) => 0; int countPlusOneCapsule(CapsuleHandle use) { return use(countCapsule) + 1; } ``` ```rust fn count_capsule(_: CapsuleHandle) -> u8 { 0 } fn count_plus_one_capsule(CapsuleHandle { mut get, .. }: CapsuleHandle) -> u8 { // Please note the following distinction in syntax based on toolchain; // the nightly syntax will be used in all remaining examples for clarity. // get.as_ref(count_capsule) + 1 // Works in stable and nightly get(count_capsule) + 1 // Works in nightly only with "experimental-api" feature } ``` -------------------------------- ### استفاده از CapsuleReader Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/core/capsules.mdx نمایش نحوه استفاده از CapsuleReader برای دسترسی به داده‌های کپسول‌های دیگر در ReArch. این مثال‌ها هم برای دارت و هم برای Rust ارائه شده‌اند و سینتکس `use(...)` و `get(...)` را نشان می‌دهند. ```dart int countCapsule(CapsuleHandle _) => 0; int countPlusOneCapsule(CapsuleHandle use) { return use(countCapsule) + 1; } ``` ```rust fn count_capsule(_: CapsuleHandle) -> u8 { 0 } fn count_plus_one_capsule(CapsuleHandle { mut get, .. }: CapsuleHandle) -> u8 { // لطفاً به تفاوت سینتکس بر اساس toolchain توجه کن؛ // توی مثال‌های بعدی برای وضوح، سینتکس nightly استفاده می‌شه. // get.as_ref(count_capsule) + 1 // توی stable و nightly کار می‌کنه get(count_capsule) + 1 // فقط توی nightly با قابلیت "experimental-api" کار می‌کنه } ``` -------------------------------- ### Inline capsule example with .map() Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/capsules.mdx Demonstrates how to use the .map() method with an inline capsule to selectively rebuild widgets based on changes to a specific index within a list. This helps optimize rebuilds by avoiding unnecessary updates to the entire list. ```dart class MyListItem extends RearchConsumer { const MyListItem(this.listIndex, {super.key}); final int listIndex; Widget build(BuildContext context, WidgetHandle use) { // With this inline capsule, we only rebuild when the data at // myList[listIndex] changes, instead of the whole myList. final dataAtIndex = use( // This creates a new inline capsule that gets a particular index of myList: myListCapsule.map((myList) => myList[listIndex]), ); return Text('$dataAtIndex'); } } ``` -------------------------------- ### Manual inline capsule example Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/capsules.mdx Illustrates how to create a manual inline capsule, which is useful when an inline capsule depends on multiple other capsules. This approach requires explicit closure definition and careful handling to prevent memory leaks. ```dart class MyListItem extends RearchConsumer { const MyListItem(this.listIndex, {super.key}); final int listIndex; Widget build(BuildContext context, WidgetHandle use) { // With this inline capsule, we only rebuild when the data at // myList[listIndex] changes, instead of the whole myList. final dataAtIndex = use( // This creates a new inline capsule that gets a particular index of myList: (CapsuleReader use) => use(myListCapsule)[listIndex], // While the following works, it is considered a bad practice // (keep reading for an explanation): // (use) => use(myListCapsule)[listIndex], ); return Text('$dataAtIndex'); } } ``` -------------------------------- ### شمارش دفعات ساخت در Rust Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/core/effects.mdx این قطعه کد نحوه شمارش دفعات ساخت یک کپسول در ReArch با استفاده از Rust را نشان می‌دهد. این مثال بر استفاده از `register` و `get` برای مدیریت وضعیت در Rust تمرکز دارد. ```rust // کپسولی که تعداد دفعاتی که ساخته می‌شه رو می‌شماره fn count_builds(CapsuleHandle { mut get ``` -------------------------------- ### Infinite Scrolling Example in Dart Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/snippets/infinite-scrolling.mdx Demonstrates creating an infinitely scrolling list using ReArch's factory pattern and automatic keep-alive. It includes a factory for delayed data echoing and a custom widget that manages its keep-alive state and displays asynchronous data. ```dart /// A factory capsule that returns the input data after a brief delay. /// This also doubles as an example of a generic capsule. Future Function(T) delayedEchoFactory(CapsuleHandle _) { return (data) => Future.delayed(const Duration(seconds: 1), () => data); } class InfiniteList extends StatelessWidget { const InfiniteList({super.key}); @override Widget build(BuildContext context) { return ListView.builder( itemBuilder: (context, index) => InfiniteScrollItem(index: index), ); } } class InfiniteScrollItem extends RearchConsumer { const InfiniteScrollItem({required this.index, super.key}); /// The index of this item. final int index; @override Widget build(BuildContext context, WidgetHandle use) { final (keepAlive, setKeepAlive) = use.state(false); use.automaticKeepAlive(keepAlive: keepAlive); final factory = use(delayedEchoFactory); final echoFuture = use.memo(() => factory(index), [factory, index]); final echoState = use.future(echoFuture); return ListTile( selected: keepAlive, onTap: () => setKeepAlive(!keepAlive), leading: Icon( keepAlive ? Icons.task_alt_rounded : Icons.radio_button_unchecked_rounded, ), title: switch (echoState) { AsyncData(:final data) => Text('$data'), AsyncLoading() => const Align( alignment: Alignment.centerLeft, child: CircularProgressIndicator.adaptive(), ), AsyncError(:final error) => Text('$error'), }, ); } } ``` -------------------------------- ### Warming up asynchronous capsules in Dart Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/paradigms/warm-up-capsules.mdx Demonstrates how to warm up asynchronous capsules in ReArch. It shows the setup for accessing SharedPreferences synchronously by first creating an asynchronous capsule, then a warm-up capsule, and finally a synchronous capsule that relies on the warmed-up value. The example also includes a `GlobalWarmUps` widget for managing multiple warm-up capsules and integrating them into the Flutter widget tree. ```dart final sharedPrefsAsyncCapsule = capsule((use) => SharedPreferences.getInstance()); final sharedPrefsWarmUpCapsule = capsule((use) { final sharedPrefsFuture = use(sharedPrefsAsyncCapsule); return use.future(sharedPrefsFuture); }); final sharedPrefsCapsule = capsule((use) => use(sharedPrefsWarmUpCapsule).dataOrElse( () => throw StateError('sharedPrefsWarmUpCapsule was not warmed up!'), )); int? count(CapsuleHandle use) { // Notice how `use` returns a synchronous `SharedPreferences`, // i.e., *not* an AsyncValue. return use(sharedPrefsCapsule).getInt('count'); } // Now, let's create our "warm up widget" class GlobalWarmUps extends RearchConsumer { const GlobalWarmUps({required this.child, super.key}); final Widget child; Widget build(BuildContext context, WidgetHandle use) { return [ // When any of the following warm up capsules error out, // the errorBuilder is invoked. // If any are still loading, the loading widget is shown. // If there are no AsyncErrors or AsyncLoadings, child is shown. // Note: all loading happens in parallel automatically // to speed up your loading times! use(sharedPrefsWarmUpCapsule), // other warm ups here... ].toWarmUpWidget( child: child, loading: const Center(child: CircularProgressIndicator.adaptive()), errorBuilder: (errors) => Column(children: [ // You might want your error display here to be prettier than this one. // You can even wrap the Column in a MaterialApp/Scaffold. for (final AsyncError(:error, :stackTrace) in errors) Text('$error\n$stackTrace'), ]), ); } } void main() { runApp(RearchBootstrapper( child: GlobalWarmUps(child: MaterialApp(...)), )); } ``` -------------------------------- ### مقداردهی شنونده با روش اعلانی در فلاتر Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/listeners.mdx این کد روشی اعلانی برای مقداردهی شنونده‌ها در فلاتر را نشان می‌دهد. با استفاده از ویجت `InitializeListeners` که از `RearchConsumer` ارث می‌برد، می‌توان شنونده‌ها را به‌صورت اعلانی ثبت کرد و از استفاده مستقیم از `CapsuleContainerProvider.containerOf` اجتناب نمود. ```flutter class InitializeListeners extends RearchConsumer { const InitializeListeners({required this.child, super.key}); final Widget child; Widget build(BuildContext context, WidgetHandle use) { use(myListener); return child; } } ``` -------------------------------- ### Create Action Capsule Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/paradigms/actions.mdx Demonstrates creating an action capsule that returns a function to increment a count. This example shows the basic structure of an action in ReArch. ```dart void Function() incrementCountAction(CapsuleHandle use) => use(countManager).$2; ``` -------------------------------- ### گرم کردن کپسول‌های گرم‌کننده ناهمزمان Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/warm-up-capsules.mdx این کد نحوه تعریف و استفاده از کپسول‌های گرم‌کننده ناهمزمان در ReArch را نشان می‌دهد. این مثال شامل تعریف کپسول‌های ناهمزمان برای SharedPreferences، ایجاد یک کپسول گرم‌کننده برای آن، و سپس استفاده از آن در یک ویجت گرم‌کننده برای مدیریت وضعیت بارگذاری و خطا است. ```dart final sharedPrefsAsyncCapsule = capsule((use) => SharedPreferences.getInstance()); final sharedPrefsWarmUpCapsule = capsule((use) { final sharedPrefsFuture = use(sharedPrefsAsyncCapsule); return use.future(sharedPrefsFuture); }); final sharedPrefsCapsule = capsule((use) => use(sharedPrefsWarmUpCapsule).dataOrElse( () => throw StateError('کپسول sharedPrefsWarmUpCapsule گرم نشده!'), )); int? count(CapsuleHandle use) { // توجه کن که `use` یه `SharedPreferences` همزمان برمی‌گردونه، // یعنی *نه* یه AsyncValue. return use(sharedPrefsCapsule).getInt('count'); } // حالا بیایم ویجت "گرم‌کننده"مون رو بسازیم class GlobalWarmUps extends RearchConsumer { const GlobalWarmUps({required this.child, super.key}); final Widget child; Widget build(BuildContext context, WidgetHandle use) { return [ // وقتی هر کدوم از کپسول‌های گرم‌کننده زیر خطا بدن، // errorBuilder فراخوانی می‌شه. // اگه هر کدوم هنوز در حال لود شدن باشن، ویجت لودینگ نشون داده می‌شه. // اگه هیچ AsyncError یا AsyncLoading وجود نداشته باشه، child نشون داده می‌شه. // توجه: همه لودینگ‌ها به‌صورت خودکار موازی انجام می‌شن // تا زمان لودینگت سریع‌تر بشه! use(sharedPrefsWarmUpCapsule), // کپسول‌های گرم‌کننده دیگه اینجا... ].toWarmUpWidget( child: child, loading: const Center(child: CircularProgressIndicator.adaptive()), errorBuilder: (errors) => Column(children: [ // شاید بخوای نمایش خطاهات اینجا قشنگ‌تر از این باشه. // حتی می‌تونی Column رو توی یه MaterialApp/Scaffold بپیچی. for (final AsyncError(:error, :stackTrace) in errors) Text('$error\n$stackTrace'), ]), ); } } void main() { runApp(RearchBootstrapper( child: GlobalWarmUps(child: MaterialApp(...)), )); } ``` -------------------------------- ### Invoice Printing and Downloading Actions Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/actions.mdx Actions for handling invoice generation and output. `invoicesPrinterCapsule` prints the invoices, while `invoicesDownloaderCapsule` allows downloading them with a specified filename. Both rely on a private `_invoicesCapsule` for the invoice data. ```dart /// صورت‌حساب‌های مشتری‌هایی که باید فاکتور بشن رو نشون می‌ده. Future _invoicesCapsule(CapsuleHandle use) => throw 'پیاده‌سازی مخفیه'; /// اکشنی که صورت‌حساب‌ها رو پرینت می‌کنه. Future Function() invoicesPrinterCapsule(CapsuleHandle use) { final invoices = use(_invoicesCapsule); return () => Printing.layoutPdf(onLayout: (_) => invoices); } /// اکشنی که صورت‌حساب‌ها رو دانلود می‌کنه. Future Function() invoicesDownloaderCapsule(CapsuleHandle use) { final invoices = use(_invoicesCapsule); final filename = use(_invoicesFilenameCapsule); // یه کپسول خصوصی دیگه return () async => Printing.sharePdf(bytes: await invoices, filename: filename); } ``` -------------------------------- ### Temporarily Listening to Capsules Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/containers.mdx Illustrates how to temporarily listen for changes in capsules using the `listen()` method. This is useful for reacting to specific data updates for a limited duration. Examples are provided for Dart and Rust. ```dart final container = CapsuleContainer(); final disposeListener = container.listen((use) => print(use(fooBarCapsule))); // When you no longer need to listen to changes: disposeListener(); ``` ```rust let container = Container::new(); let handle = container.listen(|| (), |get, ()| { println!("{}", get(foo_bar_capsule)); }); // When you no longer need to listen to changes: drop(handle); ``` -------------------------------- ### استفاده از RearchBuilder Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/snippets/widgets.mdx این کد نحوه استفاده از `RearchBuilder` را برای واگذاری ساخت ویجت به یک callback که به `WidgetHandle` و `BuildContext` دسترسی دارد، نشان می‌دهد. این زمانی مفید است که بخواهید یک `WidgetHandle` جدید را به صورت درون خطی با ویجت‌های دیگر دریافت کنید. ```dart MyWidget( child: RearchBuilder( builder: (context, use) { return Placeholder(); }, ), ); ``` -------------------------------- ### Limiting Extra Rebuilds with Conditional Usage Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/core/capsules.mdx Shows how to optimize rebuilds by conditionally using capsules. By placing the `use` or `get` call within a conditional statement, rebuilds triggered by specific dependencies are prevented when the condition is false. ```dart FooBar expensiveOperationUsingCount(CapsuleHandle use) { if (use(isWatchingCapsule)) { // داشتن این use توی یه شرط، بازسازی‌هایی که به خاطر // countCapsule وقتی isWatching فالسه ایجاد می‌شن رو متوقف می‌کنه. return someExpensiveOperation(use(countCapsule)); } return someExpensiveOperation(null); } ``` ```rust fn expensive_operation_using_count(CapsuleHandle { mut get, .. }: CapsuleHandle) -> FooBar { if get(is_watching) { // داشتن این get توی یه شرط، بازسازی‌هایی که به خاطر // count وقتی is_watching فالسه ایجاد می‌شن رو متوقف می‌کنه. some_expensive_operation(Some(get(count))) } else { some_expensive_operation(None) } } ``` -------------------------------- ### Using Side Effect Transactions Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/effects.mdx Demonstrates how to use side effect transactions to update multiple capsules simultaneously. The example shows two simple capsules (fooCapsule and barCapsule) and a resetAction that uses a transaction runner to reset both capsules. ```dart int, { void Function() increment; void Function() reset; }) fooCapsule(CapsuleHandle use) { final (state, setState) = use.state(0); return ( state, increment: () => setState(state + 1), reset: () => setState(0) ); } int, { void Function() increment; void Function() reset; }) barCapsule(CapsuleHandle use) { final (state, setState) = use.state(0); return ( state, increment: () => setState(state + 1), reset: () => setState(0) ); } void Function() resetAction(CapsuleHandle use) { final resets = [use(fooCapsule).reset, use(barCapsule).reset]; final runTxn = use.transactionRunner(); return () => runTxn(() { for (final reset in resets) { reset(); } }); } ``` ```rust fn foo_capsule( CapsuleHandle { register, .. }: CapsuleHandle, ) -> (u32, impl CData + Fn(), impl CData + Fn()) { let (state, set_state) = register(effects::state::>(0)); ( state, { let set_state = set_state.clone(); move || set_state(state + 1) }, move || set_state(0), ) } fn bar_capsule( CapsuleHandle { register, .. }: CapsuleHandle, ) -> (u32, impl CData + Fn(), impl CData + Fn()) { let (state, set_state) = register(effects::state::>(0)); ( state, { let set_state = set_state.clone(); move || set_state(state + 1) }, move || set_state(0), ) } fn reset_action(CapsuleHandle { mut get, register }: CapsuleHandle) -> impl CData + Fn() { let reset_foo = get(foo_capsule).2; let reset_bar = get(bar_capsule).2; let run_txn = register.raw(()).2; // third element of returned tuple is an Fn that runs txns move || { let reset_foo = reset_foo.clone(); let reset_bar = reset_bar.clone(); run_txn(Box::new(move || { reset_foo(); reset_bar(); })); } } ``` -------------------------------- ### Indefinitely Listening to Capsules Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/en/core/containers.mdx Explains how to set up indefinite listeners for capsule changes by creating non-idempotent capsules that register side effects. This ensures continuous updates are received throughout the container's lifetime. Examples are provided for Dart and Rust. ```dart void listener(CapsuleHandle use) { // asListener is a no-op side effect that you can use // to declare capsules as listeners use.asListener(); // Listen to your data like normal print(use(countCapsule)); } // Initialize the listener so it will get updates final container = CapsuleContainer(); container.read(listener); ``` ```rust fn listener(CapsuleHandle { mut get, register }: CapsuleHandle) { // as_listener is a no-op side effect that you can use // to declare capsules as listeners register(effects::as_listener()); // Listen to data like normal println!("{}", get(foo_bar_capsule)); } // Initialize the listener so it will get updates let container = Container::new(); container.read(listener); ``` -------------------------------- ### پیاده‌سازی شنونده بلندمدت (صحیح) Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/listeners.mdx این کد نسخه اصلاح‌شده شنونده است که با ثبت یک اثر جانبی (`use.asListener()`) به ReArch اطلاع می‌دهد که این کپسول باید به‌عنوان شنونده فعال بماند و از حذف خودکار جلوگیری می‌کند. ```dart /// نسخه اصلاح‌شده شنونده که یه اثر جانبی ثبت می‌کنه /// تا به‌صورت خودکار حذف نشه. void myListener(CapsuleHandle use) { use.asListener(); print(use(foobarCapsule)); } // و در نهایت شنونده رو یه جایی نزدیک شروع اپلیکیشنت مقداردهی کن. container.read(myListener); // فقط دارت CapsuleContainerProvider.containerOf(context).read(myListener) // فلاتر ``` -------------------------------- ### ایجاد کپسول‌های ناهمزمان Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/paradigms/async-capsules.mdx این کد نحوه ایجاد کپسول‌های ناهمزمان را در ReArch با استفاده از اثرات جانبی نشان می‌دهد. این شامل یک کپسول "خام" ناهمزمان است که مستقیماً یک Future برمی‌گرداند و یک کپسول "wrapper" که یک AsyncValue برمی‌گرداند. ```dart int countCapsule(CapsuleHandle _) => 0; /// کپسول "خام" ناهمزمان ما که مستقیماً یه Future برمی‌گردونه (می‌تونه Stream هم برگردونه). Future delayedAsyncCapsule(CapsuleHandle use) async { // همه خوندن‌های کپسول و اثرات جانبی *باید* قبل از اولین `await` باشن. // (ولی اغلب بهتره توی کپسول‌های ناهمزمان از اثرات جانبی استفاده نکنی.) final count = use(countCapsule); final delayedCount = await Future.delayed( const Duration(seconds: 1), () => count, ); return delayedCount + 1; } /// کپسول "wrapper" ما که یه AsyncValue برمی‌گردونه، و اغلب توی کد UI مفیدتره. /// این wrapper همچنین مطمئن می‌شه که مقدار delayedAsyncCapsule توی کانتینر کش می‌شه، /// چون این کپسول از یه اثر جانبی استفاده می‌کنه. /// توجه کن که می‌تونی مستقیماً از `use.future` توی کد UI هم استفاده کنی، /// اگه نمی‌خوای Future رو به‌صورت مشتاقانه (eagerly) کش کنی. AsyncValue delayedCapsule(CapsuleHandle use) { final delayed = use(delayedAsyncCapsule); return use.future(delayed); } ``` ```rust // چند راه مختلف برای این کار وجود داره، ولی روش زیر استانداردترینه. // TODO: مثال از rearch-tokio کپی بشه ``` -------------------------------- ### گوش دادن موقت به تغییرات کپسول‌ها Source: https://github.com/gregoryconrad/rearch-docs/blob/main/docs/fa/core/containers.mdx نحوه گوش دادن موقت به تغییرات یک کپسول در ReArch با استفاده از متد listen(). این مثال نحوه ثبت یک شنونده و لغو ثبت آن را نشان می‌دهد. ```dart final container = CapsuleContainer(); final disposeListener = container.listen((use) => print(use(fooBarCapsule))); // وقتی دیگه نیازی به گوش دادن به تغییرات نداری: disposeListener(); ``` ```rust let container = Container::new(); let handle = container.listen(|| (), |get, ()| { println!("{}", get(foo_bar_capsule)); }); // وقتی دیگه نیازی به گوش دادن به تغییرات نداری: drop(handle); ```