wip: rename fc to component

This commit is contained in:
Jonathan Kelley committed 2021-12-09 21:19:31 -05:00
1 parent 85ab8b91c6
commit 1e4a599d14
61 files changed
+524 -145

No files matched your search

+3
View File
@@ -9,3 +9,6 @@ pub use use_shared_state::*;
mod usecoroutine;
pub use usecoroutine::*;
mod usemodel;
pub use usemodel::*;
+17 -5
View File
@@ -8,7 +8,7 @@ use std::{
type ProvidedState<T> = RefCell<ProvidedStateInner<T>>;
// Tracks all the subscribers to a shared State
pub(crate) struct ProvidedStateInner<T> {
pub struct ProvidedStateInner<T> {
value: Rc<RefCell<T>>,
notify_any: Rc<dyn Fn(ScopeId)>,
consumers: HashSet<ScopeId>,
@@ -20,6 +20,14 @@ impl<T> ProvidedStateInner<T> {
(self.notify_any)(*consumer);
}
}
pub fn write(&self) -> RefMut<T> {
self.value.borrow_mut()
}
pub fn read(&self) -> Ref<T> {
self.value.borrow()
}
}
/// This hook provides some relatively light ergonomics around shared state.
@@ -114,10 +122,10 @@ impl<'a, T: 'static> UseSharedState<'a, T> {
}
pub fn notify_consumers(self) {
// if !self.needs_notification.get() {
self.root.borrow_mut().notify_consumers();
// self.needs_notification.set(true);
// }
if !self.needs_notification.get() {
self.root.borrow_mut().notify_consumers();
self.needs_notification.set(true);
}
}
pub fn read_write(&self) -> (Ref<'_, T>, &Self) {
@@ -138,6 +146,10 @@ impl<'a, T: 'static> UseSharedState<'a, T> {
pub fn write_silent(&self) -> RefMut<'_, T> {
self.value.borrow_mut()
}
pub fn inner(&self) -> Rc<RefCell<ProvidedStateInner<T>>> {
self.root.clone()
}
}
impl<T> Copy for UseSharedState<'_, T> {}
+8 -3
View File
@@ -6,9 +6,9 @@ use std::{
rc::Rc,
};
pub fn use_coroutine<'a, F: Future<Output = ()> + 'a>(
pub fn use_coroutine<'a, F: Future<Output = ()> + 'static>(
cx: Context<'a>,
f: impl FnOnce() -> F + 'a,
mut f: impl FnMut() -> F + 'a,
) -> CoroutineHandle {
//
cx.use_hook(
@@ -62,7 +62,7 @@ pub struct CoroutineHandle<'a> {
impl<'a> CoroutineHandle<'a> {
pub fn start(&self) {
if self.inner.running.get() {
if self.is_running() {
return;
}
if let Some(submit) = self.inner.submit.borrow_mut().take() {
@@ -71,5 +71,10 @@ impl<'a> CoroutineHandle<'a> {
self.cx.push_task(|| fut.as_mut().unwrap().as_mut());
}
}
pub fn is_running(&self) -> bool {
self.inner.running.get()
}
pub fn resume(&self) {}
}
+136
View File
@@ -0,0 +1,136 @@
//! When building complex components, it's occasionally useful to dip into a pure MVC pattern instead of the
//! React hooks pattern. Hooks are useful to abstract over some reusable logic, but many models are not reusable
//! in the same way that hooks are.
//!
//! In these cases, we provide `use_model` - a convenient way of abstracting over some state and async functions.
use dioxus_core::prelude::Context;
use futures::Future;
use std::{
cell::{Cell, Ref, RefCell, RefMut},
marker::PhantomData,
pin::Pin,
rc::Rc,
};
pub fn use_model<T: 'static>(cx: Context, f: impl FnOnce() -> T) -> UseModel<T> {
cx.use_hook(
|_| UseModelInner {
update_scheduled: Cell::new(false),
update_callback: cx.schedule_update(),
value: RefCell::new(f()),
// tasks: RefCell::new(Vec::new()),
},
|inner| {
inner.update_scheduled.set(false);
UseModel { inner }
},
)
}
pub struct UseModel<'a, T> {
inner: &'a UseModelInner<T>,
}
struct UseModelInner<T> {
update_scheduled: Cell<bool>,
update_callback: Rc<dyn Fn()>,
value: RefCell<T>,
// tasks: RefCell<Vec<ModelTask>>,
}
type ModelTask = Pin<Box<dyn Future<Output = ()> + 'static>>;
impl<'a, T: 'static> UseModel<'a, T> {
pub fn read(&self) -> Ref<'_, T> {
self.inner.value.borrow()
}
pub fn write(&self) -> RefMut<'_, T> {
self.needs_update();
self.inner.value.borrow_mut()
}
/// Allows the ability to write the value without forcing a re-render
pub fn write_silent(&self) -> RefMut<'_, T> {
self.inner.value.borrow_mut()
}
pub fn needs_update(&self) {
if !self.inner.update_scheduled.get() {
self.inner.update_scheduled.set(true);
(self.inner.update_callback)();
}
}
pub fn set(&self, new: T) {
*self.inner.value.borrow_mut() = new;
self.needs_update();
}
pub fn read_write(&self) -> (Ref<'_, T>, &Self) {
(self.read(), self)
}
pub fn start(&self, f: impl FnOnce() -> ModelTask) {
todo!()
}
}
// keep a coroutine going
pub fn use_model_coroutine<T, F: Future<Output = ()> + 'static>(
cx: Context,
model: UseModel<T>,
f: impl FnOnce(AppModels) -> F,
) -> UseModelCoroutine {
cx.use_hook(
|_| {
//
UseModelTaskInner {
task: Default::default(),
}
},
|inner| {
if let Some(task) = inner.task.get_mut() {
cx.push_task(|| task);
}
//
todo!()
},
)
}
pub struct UseModelCoroutine {}
struct UseModelTaskInner {
task: RefCell<Option<ModelTask>>,
}
impl UseModelCoroutine {
pub fn start(&self) {}
}
pub struct ModelAsync<T> {
_p: PhantomData<T>,
}
impl<T> ModelAsync<T> {
pub fn write(&self) -> RefMut<'_, T> {
todo!()
}
pub fn read(&self) -> Ref<'_, T> {
todo!()
}
}
pub struct AppModels {}
impl AppModels {
pub fn get<T: 'static>(&self) -> ModelAsync<T> {
unimplemented!()
}
}
impl<T> Copy for UseModel<'_, T> {}
impl<'a, T> Clone for UseModel<'a, T> {
fn clone(&self) -> Self {
Self { inner: self.inner }
}
}
+5 -5
View File
@@ -8,12 +8,12 @@ use dioxus_core::Context;
pub fn use_ref<T: 'static>(cx: Context, f: impl FnOnce() -> T) -> UseRef<T> {
cx.use_hook(
|_| UseRefInner {
update_scheuled: Cell::new(false),
update_scheduled: Cell::new(false),
update_callback: cx.schedule_update(),
value: RefCell::new(f()),
},
|inner| {
inner.update_scheuled.set(false);
inner.update_scheduled.set(false);
UseRef { inner }
},
)
@@ -23,7 +23,7 @@ pub struct UseRef<'a, T> {
inner: &'a UseRefInner<T>,
}
struct UseRefInner<T> {
update_scheuled: Cell<bool>,
update_scheduled: Cell<bool>,
update_callback: Rc<dyn Fn()>,
value: RefCell<T>,
}
@@ -54,8 +54,8 @@ impl<'a, T> UseRef<'a, T> {
}
pub fn needs_update(&self) {
if !self.inner.update_scheuled.get() {
self.inner.update_scheuled.set(true);
if !self.inner.update_scheduled.get() {
self.inner.update_scheduled.set(true);
(self.inner.update_callback)();
}
}
+16 -10
View File
@@ -8,7 +8,7 @@ use std::{
/// Store state between component renders!
///
/// ## The "Pinnacle" of state hooks
/// ## Dioxus equivalent of useState, designed for Rust
///
/// The Dioxus version of `useState` is the "king daddy" of state management. It allows you to ergonomically store and
/// modify state between component renders. When the state is updated, the component will re-render.
@@ -54,17 +54,15 @@ pub fn use_state<'a, T: 'static>(
initial_state_fn: impl FnOnce() -> T,
) -> UseState<'a, T> {
cx.use_hook(
move |_| {
//
UseStateInner {
current_val: initial_state_fn(),
update_callback: cx.schedule_update(),
wip: Rc::new(RefCell::new(None)),
update_scheuled: Cell::new(false),
}
move |_| UseStateInner {
current_val: initial_state_fn(),
update_callback: cx.schedule_update(),
wip: Rc::new(RefCell::new(None)),
update_scheuled: Cell::new(false),
},
move |hook| {
hook.update_scheuled.set(false);
let mut new_val = hook.wip.borrow_mut();
if new_val.is_some() {
hook.current_val = new_val.take().unwrap();
@@ -134,13 +132,13 @@ impl<'a, T: 'static> UseState<'a, T> {
pub fn setter(&self) -> Rc<dyn Fn(T)> {
let slot = self.inner.wip.clone();
Rc::new(move |new| {
//
*slot.borrow_mut() = Some(new);
})
}
pub fn for_async(&self) -> AsyncUseState<T> {
AsyncUseState {
re_render: self.inner.update_callback.clone(),
wip: self.inner.wip.clone(),
}
}
@@ -169,6 +167,10 @@ impl<'a, T: 'static + ToOwned<Owned = T>> UseState<'a, T> {
slot.as_mut().unwrap()
})
}
pub fn inner(self) -> T {
self.inner.current_val.to_owned()
}
}
impl<'a, T> std::ops::Deref for UseState<'a, T> {
@@ -254,6 +256,7 @@ impl<'a, T: 'static + Display> std::fmt::Display for UseState<'a, T> {
/// A less ergonmic but still capable form of use_state that's valid for `static lifetime
pub struct AsyncUseState<T: 'static> {
re_render: Rc<dyn Fn()>,
wip: Rc<RefCell<Option<T>>>,
}
@@ -269,7 +272,10 @@ impl<T: ToOwned> AsyncUseState<T> {
slot.as_mut().unwrap()
})
}
}
impl<T> AsyncUseState<T> {
pub fn set(&mut self, val: T) {
(self.re_render)();
*self.wip.borrow_mut() = Some(val);
}
}