docs: move into a fromjs tutorial

This commit is contained in:
Jonathan Kelley committed 2021-06-03 12:02:46 -04:00
1 parent b05331a60b
commit 69f5cc3802
10 files changed
+92 -113

No files matched your search

+11 -11
View File
@@ -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 => {
+1
View File
@@ -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;
+30 -49
View File
@@ -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
// ==================================================================================