WIP: Todomvc in progress
This commit is contained in:
1 parent
0d44f009b0
commit
b843dbd367
10 files changed
+416
-219
No files matched your search
@@ -1,9 +1,11 @@
|
||||
[package]
|
||||
name = "dioxus-recoil"
|
||||
name = "recoil"
|
||||
version = "0.0.0"
|
||||
authors = ["Jonathan Kelley <jkelleyrtp@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
[dependencies]
|
||||
dioxus-core = { path = "../core" }
|
||||
uuid = "0.8.2"
|
||||
@@ -1,13 +1,17 @@
|
||||
# Recoil.rs
|
||||
# Recoil.rs - Official global state management solution for Dioxus Apps
|
||||
|
||||
Recoil.rs provides a global state management API for Dioxus apps built on the concept of "atomic state." Instead of grouping state together into a single bundle ALA Redux, Recoil provides individual building blocks of state called Atoms. These atoms can be set/get anywhere in the app and combined to craft complex state. Recoil should be easier to learn and more efficient than Redux. Recoil.rs is modeled after the Recoil.JS project and pulls in
|
||||
|
||||
Recoil.rs is officially supported by the Dioxus team. By doing so, are are "planting our flag in the stand" for atomic state management instead of bundled (Redux-style) state management. Atomic state management fits well with the internals of Dioxus, meaning Recoil.rs state management will be faster, more efficient, and less sensitive to data races than Redux-style apps.
|
||||
|
||||
Internally, Dioxus uses batching to speed up linear-style operations. Recoil.rs integrates with this batching optimization, making app-wide changes extremely fast. This way, Recoil.rs can be pushed significantly harder than Redux without the need to enable/disable debug flags to prevent performance slowdowns.
|
||||
|
||||
## Guide
|
||||
|
||||
A simple atom of state is defined globally as a const:
|
||||
A simple atom of state is defined globally as a static:
|
||||
|
||||
```rust
|
||||
static Light: Atom<&'static str> = atom(|_| "Green");
|
||||
const Light: Atom<&'static str> = atom(|_| "Green");
|
||||
```
|
||||
|
||||
This atom of state is initialized with a value of `"Green"`. The atom that is returned does not actually contain any values. Instead, the atom's key - which is automatically generated in this instance - is used in the context of a Recoil App.
|
||||
@@ -16,7 +20,7 @@ This is then later used in components like so:
|
||||
|
||||
```rust
|
||||
fn App(ctx: Context, props: &()) -> DomTree {
|
||||
// The recoil root must be initialized at the top of the application before any uses
|
||||
// The recoil root must be initialized at the top of the application before any use_recoils
|
||||
recoil::init_recoil_root(&ctx, |_| {});
|
||||
|
||||
let color = use_recoil(&ctx, &TITLE);
|
||||
|
||||
+130
-5
@@ -1,7 +1,132 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
// ========================
|
||||
// Important hooks
|
||||
// ========================
|
||||
|
||||
pub fn init_recoil_root(ctx: Context) {}
|
||||
|
||||
pub fn use_recoil_value() {}
|
||||
|
||||
pub fn use_recoil() {}
|
||||
|
||||
pub fn use_set_recoil() {}
|
||||
|
||||
use dioxus_core::virtual_dom::Context;
|
||||
|
||||
pub struct RecoilContext {}
|
||||
|
||||
impl RecoilContext {
|
||||
/// Get the value of an atom. Returns a reference to the underlying data.
|
||||
pub fn get<T: PartialEq>(&self, t: &'static Atom<T>) -> &T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Replace an existing value with a new value
|
||||
///
|
||||
/// This does not replace the value instantly.
|
||||
/// All calls to "get" will return the old value until the component is rendered.
|
||||
pub fn set<T: PartialEq, O>(&self, t: &'static Atom<T>, new: T) {
|
||||
self.modify(t, move |old| *old = new);
|
||||
}
|
||||
|
||||
/// Modify lets you modify the value in place. However, because there's no previous value around to compare
|
||||
/// the new one with, we are unable to memoize the change. As such, all downsteam users of this Atom will
|
||||
/// be updated, causing all subsrcibed components to re-render.
|
||||
///
|
||||
/// This is fine for most values, but might not be performant when dealing with collections. For collections,
|
||||
/// use the "Family" variants as these will stay memoized for inserts, removals, and modifications.
|
||||
///
|
||||
/// Note - like "set" this won't propogate instantly. Once all "gets" are dropped, only then will the update occur
|
||||
pub fn modify<T: PartialEq, O>(&self, t: &'static Atom<T>, f: impl FnOnce(&mut T) -> O) -> O {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn use_recoil_context<T>(c: Context) -> &T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// pub fn use_callback<'a>(c: &Context<'a>, f: impl Fn() -> G) -> &'a RecoilContext {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
pub fn use_atom<'a, T: PartialEq>(c: Context<'a>, t: &'static Atom<T>) -> &'a T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub trait Readable {}
|
||||
impl<T: PartialEq> Readable for &'static Atom<T> {}
|
||||
impl<K: PartialEq, V: PartialEq> Readable for &'static AtomFamily<K, V> {}
|
||||
|
||||
pub fn use_atom_family<'a, K: PartialEq, V: PartialEq>(
|
||||
c: &Context<'a>,
|
||||
t: &'static AtomFamily<K, V>,
|
||||
g: K,
|
||||
) -> &'a V {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub struct AtomBuilder<T: PartialEq> {
|
||||
pub key: String,
|
||||
pub manual_init: Option<Box<dyn Fn() -> T>>,
|
||||
_never: std::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: PartialEq> AtomBuilder<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
key: "".to_string(),
|
||||
manual_init: None,
|
||||
_never: std::marker::PhantomData {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init<A: Fn() -> T + 'static>(&mut self, f: A) {
|
||||
self.manual_init = Some(Box::new(f));
|
||||
}
|
||||
|
||||
pub fn set_key(&mut self, _key: &'static str) {}
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Atom
|
||||
// =====================================
|
||||
pub struct atom<T: PartialEq>(pub fn(&mut AtomBuilder<T>) -> T);
|
||||
pub type Atom<T: PartialEq> = atom<T>;
|
||||
|
||||
// =====================================
|
||||
// Atom Family
|
||||
// =====================================
|
||||
pub struct AtomFamilyBuilder<K, V> {
|
||||
_never: std::marker::PhantomData<(K, V)>,
|
||||
}
|
||||
|
||||
pub struct atom_family<K: PartialEq, V: PartialEq>(pub fn(&mut AtomFamilyBuilder<K, V>));
|
||||
pub type AtomFamily<K: PartialEq, V: PartialEq> = atom_family<K, V>;
|
||||
|
||||
// =====================================
|
||||
// Selectors
|
||||
// =====================================
|
||||
pub struct SelectorApi {}
|
||||
impl SelectorApi {
|
||||
pub fn get<T: PartialEq>(&self, t: &'static Atom<T>) -> &T {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
// pub struct SelectorBuilder<Out, const Built: bool> {
|
||||
// _p: std::marker::PhantomData<Out>,
|
||||
// }
|
||||
// impl<O> SelectorBuilder<O, false> {
|
||||
// pub fn getter(self, f: impl Fn(()) -> O) -> SelectorBuilder<O, true> {
|
||||
// todo!()
|
||||
// // std::rc::Rc::pin(value)
|
||||
// // todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
pub struct selector<O>(pub fn(&SelectorApi) -> O);
|
||||
// pub struct selector<O>(pub fn(SelectorBuilder<O, false>) -> SelectorBuilder<O, true>);
|
||||
pub type Selector<O> = selector<O>;
|
||||
|
||||
pub fn use_selector<'a, O>(c: Context<'a>, s: &'static Selector<O>) -> &'a O {
|
||||
todo!()
|
||||
}
|
||||
Reference in new issue
Block a user