docs: move into a fromjs tutorial
This commit is contained in:
1 parent
b05331a60b
commit
69f5cc3802
10 files changed
+92
-113
No files matched your search
+11
-11
@@ -29,7 +29,7 @@ mod use_state_def {
|
||||
/// Usage:
|
||||
/// ```ignore
|
||||
/// static Example: FC<()> = |ctx| {
|
||||
/// let (counter, set_counter) = use_state(ctx, || 0);
|
||||
/// let (counter, set_counter) = use_state(&ctx, || 0);
|
||||
/// let increment = |_| set_couter(counter + 1);
|
||||
/// let decrement = |_| set_couter(counter + 1);
|
||||
///
|
||||
@@ -42,8 +42,8 @@ mod use_state_def {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T, P: 'a>(
|
||||
ctx: Context<'a, P>,
|
||||
pub fn use_state<'a, 'c, T: 'static, F: FnOnce() -> T>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
initial_state_fn: F,
|
||||
) -> (&'a T, &'a Rc<dyn Fn(T)>) {
|
||||
struct UseState<T: 'static> {
|
||||
@@ -156,7 +156,7 @@ mod new_use_state_def {
|
||||
/// Usage:
|
||||
/// ```ignore
|
||||
/// static Example: FC<()> = |ctx| {
|
||||
/// let (counter, set_counter) = use_state(ctx, || 0);
|
||||
/// let (counter, set_counter) = use_state(&ctx, || 0);
|
||||
/// let increment = |_| set_couter(counter + 1);
|
||||
/// let decrement = |_| set_couter(counter + 1);
|
||||
///
|
||||
@@ -169,8 +169,8 @@ mod new_use_state_def {
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_state_new<'a, 'c, T: 'static, F: FnOnce() -> T, P: 'static>(
|
||||
ctx: Context<'a, P>,
|
||||
pub fn use_state_new<'a, 'c, T: 'static, F: FnOnce() -> T>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
initial_state_fn: F,
|
||||
) -> &'a UseState<T> {
|
||||
ctx.use_hook(
|
||||
@@ -246,8 +246,8 @@ mod use_ref_def {
|
||||
/// To change it, use modify.
|
||||
/// Modifications to this value do not cause updates to the component
|
||||
/// Attach to inner context reference, so context can be consumed
|
||||
pub fn use_ref<'a, T: 'static, P>(
|
||||
ctx: Context<'a, P>,
|
||||
pub fn use_ref<'a, T: 'static>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
initial_state_fn: impl FnOnce() -> T + 'static,
|
||||
) -> &'a RefCell<T> {
|
||||
ctx.use_hook(|| RefCell::new(initial_state_fn()), |state| &*state, |_| {})
|
||||
@@ -270,8 +270,8 @@ mod use_reducer_def {
|
||||
///
|
||||
/// This is behaves almost exactly the same way as React's "use_state".
|
||||
///
|
||||
pub fn use_reducer<'a, 'c, State: 'static, Action: 'static, P: 'static>(
|
||||
ctx: Context<'a, P>,
|
||||
pub fn use_reducer<'a, 'c, State: 'static, Action: 'static>(
|
||||
ctx: &impl Scoped<'a>,
|
||||
initial_state_fn: impl FnOnce() -> State,
|
||||
_reducer: impl Fn(&mut State, Action),
|
||||
) -> (&'a State, &'a Box<dyn Fn(Action)>) {
|
||||
@@ -348,7 +348,7 @@ mod use_reducer_def {
|
||||
}
|
||||
|
||||
pub fn use_is_initialized<P>(ctx: Context<P>) -> bool {
|
||||
let val = use_ref(ctx, || false);
|
||||
let val = use_ref(&ctx, || false);
|
||||
match *val.borrow() {
|
||||
true => true,
|
||||
false => {
|
||||
|
||||
@@ -115,6 +115,7 @@ pub mod prelude {
|
||||
pub use crate::component::{fc_to_builder, Properties};
|
||||
use crate::nodes;
|
||||
pub use crate::virtual_dom::Context;
|
||||
pub use crate::virtual_dom::Scoped;
|
||||
pub use nodes::*;
|
||||
|
||||
pub use crate::nodebuilder::LazyNodes;
|
||||
|
||||
@@ -526,6 +526,9 @@ pub struct Scope {
|
||||
pub(crate) listeners: RefCell<Vec<*const dyn Fn(VirtualEvent)>>,
|
||||
}
|
||||
|
||||
// We need to pin the hook so it doesn't move as we initialize the list of hooks
|
||||
type Hook = Pin<Box<dyn std::any::Any>>;
|
||||
|
||||
impl Scope {
|
||||
// we are being created in the scope of an existing component (where the creator_node lifetime comes into play)
|
||||
// we are going to break this lifetime by force in order to save it on ourselves.
|
||||
@@ -718,36 +721,27 @@ impl<'a, T> Deref for Context<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'src, T> Context<'src, T> {
|
||||
impl<'src, T> Scoped<'src> for Context<'src, T> {
|
||||
fn get_scope(&self) -> &'src Scope {
|
||||
self.scope
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Scoped<'src>: Sized {
|
||||
fn get_scope(&self) -> &'src Scope;
|
||||
|
||||
/// Access the children elements passed into the component
|
||||
pub fn children(&self) -> &'src [VNode<'src>] {
|
||||
fn children(&self) -> &'src [VNode<'src>] {
|
||||
todo!("Children API not yet implemented for component Context")
|
||||
}
|
||||
|
||||
/// Create a subscription that schedules a future render for the reference component
|
||||
pub fn schedule_update(&self) -> Rc<dyn Fn() + 'static> {
|
||||
fn schedule_update(&self) -> Rc<dyn Fn() + 'static> {
|
||||
todo!()
|
||||
// pub fn schedule_update(self) -> impl Fn() + 'static {
|
||||
// self.scope.event_queue.schedule_update(&self.scope)
|
||||
}
|
||||
|
||||
// /// Create a suspended component from a future.
|
||||
// ///
|
||||
// /// When the future completes, the component will be renderered
|
||||
// pub fn suspend<'a, F: for<'b> FnOnce(&'b NodeCtx<'a>) -> VNode<'a> + 'a>(
|
||||
// &'a self,
|
||||
// _fut: impl Future<Output = LazyNodes<'a, F>>,
|
||||
// ) -> VNode<'src> {
|
||||
// todo!()
|
||||
// }
|
||||
}
|
||||
|
||||
// ================================================
|
||||
// Render Implementation for Components
|
||||
// ================================================
|
||||
//
|
||||
impl<'src, T> Context<'src, T> {
|
||||
// impl<'scope> Context<'scope> {
|
||||
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
|
||||
///
|
||||
/// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
|
||||
@@ -763,14 +757,15 @@ impl<'src, T> Context<'src, T> {
|
||||
/// ctx.render(lazy_tree)
|
||||
/// }
|
||||
///```
|
||||
pub fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
fn render<'a, F: for<'b> FnOnce(&'b NodeCtx<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
self,
|
||||
// &'a/ self,
|
||||
lazy_nodes: LazyNodes<'src, F>,
|
||||
// lazy_nodes: LazyNodes<'src, F>,
|
||||
) -> VNode<'src> {
|
||||
let scope_ref = self.get_scope();
|
||||
let ctx = NodeCtx {
|
||||
scope_ref: self.scope,
|
||||
scope_ref,
|
||||
listener_id: 0.into(),
|
||||
};
|
||||
|
||||
@@ -781,16 +776,7 @@ impl<'src, T> Context<'src, T> {
|
||||
// },
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================
|
||||
// Hooks Implementation for Components
|
||||
// ================================================
|
||||
|
||||
// We need to pin the hook so it doesn't move as we initialize the list of hooks
|
||||
type Hook = Pin<Box<dyn std::any::Any>>;
|
||||
|
||||
impl<'src, T> Context<'src, T> {
|
||||
// impl<'scope> Context<'scope> {
|
||||
/// Store a value between renders
|
||||
///
|
||||
@@ -808,7 +794,7 @@ impl<'src, T> Context<'src, T> {
|
||||
/// )
|
||||
/// }
|
||||
/// ```
|
||||
pub fn use_hook<InternalHookState: 'static, Output: 'src>(
|
||||
fn use_hook<InternalHookState: 'static, Output: 'src>(
|
||||
&self,
|
||||
|
||||
// The closure that builds the hook state
|
||||
@@ -821,10 +807,12 @@ impl<'src, T> Context<'src, T> {
|
||||
// TODO: add this to the "clean up" group for when the component is dropped
|
||||
_cleanup: impl FnOnce(InternalHookState),
|
||||
) -> Output {
|
||||
let idx = *self.scope.hookidx.borrow();
|
||||
let scope = self.get_scope();
|
||||
|
||||
let idx = *scope.hookidx.borrow();
|
||||
|
||||
// Grab out the hook list
|
||||
let mut hooks = self.scope.hooks.borrow_mut();
|
||||
let mut hooks = scope.hooks.borrow_mut();
|
||||
|
||||
// If the idx is the same as the hook length, then we need to add the current hook
|
||||
if idx >= hooks.len() {
|
||||
@@ -832,7 +820,7 @@ impl<'src, T> Context<'src, T> {
|
||||
hooks.push(Box::pin(new_state));
|
||||
}
|
||||
|
||||
*self.scope.hookidx.borrow_mut() += 1;
|
||||
*scope.hookidx.borrow_mut() += 1;
|
||||
|
||||
let stable_ref = hooks
|
||||
.get_mut(idx)
|
||||
@@ -854,12 +842,7 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
// We extend the lifetime of the internal state
|
||||
runner(unsafe { &mut *(internal_state as *mut _) })
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================
|
||||
// Context API Implementation for Components
|
||||
// ================================================
|
||||
impl<'src, P> Context<'src, P> {
|
||||
/// This hook enables the ability to expose state to children further down the VirtualDOM Tree.
|
||||
///
|
||||
/// This is a hook, so it may not be called conditionally!
|
||||
@@ -872,8 +855,9 @@ impl<'src, P> Context<'src, P> {
|
||||
///
|
||||
///
|
||||
///
|
||||
pub fn use_create_context<T: 'static>(&self, init: impl Fn() -> T) {
|
||||
let mut ctxs = self.scope.shared_contexts.borrow_mut();
|
||||
fn use_create_context<T: 'static>(&self, init: impl Fn() -> T) {
|
||||
let scope = self.get_scope();
|
||||
let mut ctxs = scope.shared_contexts.borrow_mut();
|
||||
let ty = TypeId::of::<T>();
|
||||
|
||||
let is_initialized = self.use_hook(
|
||||
@@ -901,12 +885,12 @@ impl<'src, P> Context<'src, P> {
|
||||
}
|
||||
|
||||
/// There are hooks going on here!
|
||||
pub fn use_context<T: 'static>(&self) -> &'src Rc<T> {
|
||||
fn use_context<T: 'static>(&self) -> &'src Rc<T> {
|
||||
self.try_use_context().unwrap()
|
||||
}
|
||||
|
||||
/// Uses a context, storing the cached value around
|
||||
pub fn try_use_context<T: 'static>(&self) -> Result<&'src Rc<T>> {
|
||||
fn try_use_context<T: 'static>(&self) -> Result<&'src Rc<T>> {
|
||||
struct UseContextHook<C> {
|
||||
par: Option<Rc<C>>,
|
||||
we: Option<Weak<C>>,
|
||||
@@ -918,7 +902,8 @@ impl<'src, P> Context<'src, P> {
|
||||
we: None as Option<Weak<T>>,
|
||||
},
|
||||
move |hook| {
|
||||
let mut scope = Some(self.scope);
|
||||
let scope = self.get_scope();
|
||||
let mut scope = Some(scope);
|
||||
|
||||
if let Some(we) = &hook.we {
|
||||
if let Some(re) = we.upgrade() {
|
||||
@@ -964,10 +949,6 @@ impl<'src, P> Context<'src, P> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait OpaqueScope {
|
||||
fn get_scope(&self) -> &Scope;
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
// Supporting structs for the above abstractions
|
||||
// ==================================================================================
|
||||
|
||||
Reference in new issue
Block a user