wip: parity document
This commit is contained in:
parent
ee67654f58
commit
ba975410f9
|
@ -5,6 +5,10 @@ Welcome to the first iteration of the Dioxus Virtual DOM! This release brings su
|
|||
- Server-rendering with custom ToString implementation
|
||||
- State management
|
||||
- Build CLI
|
||||
- Foundational hooks
|
||||
- Context API
|
||||
- Basic suspense
|
||||
- Controlled components
|
||||
----
|
||||
## Project: Initial VDOM support (TBD)
|
||||
> Get the initial VDom + Event System + Patching + Diffing + Component framework up and running
|
||||
|
@ -80,18 +84,25 @@ Welcome to the first iteration of the Dioxus Virtual DOM! This release brings su
|
|||
- [x] Tweak macro parsing for better errors
|
||||
- [x] dirty tagging, compression
|
||||
- [x] code health
|
||||
- [ ] name spacing so svg works
|
||||
- [ ] fix keys on elements
|
||||
- [ ] controlled components (kinda tuff since we need all these different platforms)
|
||||
- [ ] Their own crate
|
||||
- [ ] Re-exported through the `dioxus` crate (not core)
|
||||
- [ ] Hooks
|
||||
- [ ] Re-exported through the `dioxus` crate (not essential to core virtualdom)
|
||||
|
||||
## Less-essential todos
|
||||
- [ ] Make events lazy (use traits + Box<dyn>) - not sure what this means anymore
|
||||
- [ ] Beef up the dioxus CLI tool to report build progress
|
||||
- [ ] Extract arena logic out for better safety guarantees
|
||||
- [ ] Extract BumpFrame logic out for better safety guarantees
|
||||
- [ ] make SSR follow HTML spec
|
||||
- [ ] fix keys on elements
|
||||
- [ ] MIRI tests
|
||||
- [ ] all synthetic events filled out
|
||||
- [ ] double check event targets and stuff
|
||||
- [ ] Documentation overhaul
|
||||
- [ ] Website
|
||||
- [ ] controlled components
|
||||
|
||||
lower priority features
|
||||
- [ ] Attributes on elements should implement format_args instead of string fmt
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# Parity with React
|
||||
|
||||
Sorted by priority
|
||||
|
||||
| Feature | Dioxus | React |
|
||||
| ---------------------- | ------ | ----- |
|
||||
| Conditional Rendering | ✅ | ✅ |
|
||||
| Map, Iterator | ✅ | ✅ |
|
||||
| Keyed Components | ✅ | ✅ |
|
||||
| Web | ✅ | ✅ |
|
||||
| Desktop (webview) | ✅ | ✅ |
|
||||
| Context | ✅ | ✅ |
|
||||
| Hook | ✅ | ✅ |
|
||||
| SSR | ✅ | ✅ |
|
||||
| Runs natively | ✅ | 👀 |
|
||||
| Null components | 👀 | ✅ |
|
||||
| Fragments | 👀 | ✅ |
|
||||
| Component Children | 👀 | ✅ |
|
||||
| NodeRef | 👀 | ✅ |
|
||||
| Controlled Inputs | 👀 | ✅ |
|
||||
| No-div components | 👀 | ✅ |
|
||||
| CSS/Inline Styles | 👀 | ✅ |
|
||||
| 1st class global state | 👀 | ✅ |
|
||||
| -------------------- | ----- | ----- |
|
||||
| 1st class router | 👀 | ✅ |
|
||||
| Suspense | 👀 | 👀 |
|
||||
| Animation | 👀 | ✅ |
|
||||
| Mobile | 👀 | ✅ |
|
||||
| Desktop (native) | 👀 | ✅ |
|
||||
| 3D Renderer | 👀 | ✅ |
|
||||
| -------------------- | ----- | ----- |
|
||||
| Portal | 👀 | ✅ |
|
||||
| Error boundary | 👀 | ✅ |
|
||||
| Code-splitting | 👀 | ✅ |
|
|
@ -8,8 +8,8 @@ edition = "2018"
|
|||
|
||||
[dependencies]
|
||||
dioxus-core = { path = "../core" }
|
||||
uuid = "0.8.2"
|
||||
|
||||
[dev-dependencies]
|
||||
uuid = { version = "0.8.2", features = ["v4"] }
|
||||
dioxus-web = { path = "../web" }
|
||||
wasm-bindgen-futures = "*"
|
||||
|
|
|
@ -2,16 +2,22 @@ use std::collections::HashMap;
|
|||
|
||||
use dioxus_core::prelude::*;
|
||||
use recoil::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
const TODOS: AtomFamily<&str, Todo> = |_| HashMap::new();
|
||||
const TODOS: AtomFamily<Uuid, Todo> = |_| HashMap::new();
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct Todo {
|
||||
checked: bool,
|
||||
title: String,
|
||||
contents: String,
|
||||
}
|
||||
|
||||
static App: FC<()> = |ctx, _| {
|
||||
use_init_recoil_root(ctx);
|
||||
|
||||
let todos = use_recoil_family(ctx, &TODOS);
|
||||
|
||||
rsx! { in ctx,
|
||||
div {
|
||||
"Basic Todolist with AtomFamilies in Recoil.rs"
|
||||
|
@ -19,11 +25,20 @@ static App: FC<()> = |ctx, _| {
|
|||
}
|
||||
};
|
||||
|
||||
static Child: FC<()> = |ctx, _| {
|
||||
// let todo = use_recoil_value(ctx, &TODOS);
|
||||
#[derive(Props, PartialEq)]
|
||||
struct ChildProps {
|
||||
id: Uuid,
|
||||
}
|
||||
|
||||
static Child: FC<ChildProps> = |ctx, props| {
|
||||
let (todo, set_todo) = use_recoil_state(ctx, &TODOS.select(&props.id));
|
||||
|
||||
rsx! { in ctx,
|
||||
div {
|
||||
|
||||
h1 {"{todo.title}"}
|
||||
input { type: "checkbox", name: "scales", checked: "{todo.checked}" }
|
||||
label { "{todo.contents}", for: "scales" }
|
||||
p {"{todo.contents}"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,8 +18,9 @@ const D_SELECTOR: SelectorFamilyBorrowed<i32, i32> = |api, key| -> &i32 {
|
|||
};
|
||||
|
||||
static App: FC<()> = |ctx, _| {
|
||||
let title = use_recoil_value(ctx, &C_SELECTOR);
|
||||
use_init_recoil_root(ctx);
|
||||
|
||||
let title = use_recoil_value(ctx, &C_SELECTOR);
|
||||
let title = "";
|
||||
rsx! { in ctx,
|
||||
div {
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct CollectionSelection<T> {
|
|||
_never: PhantomData<T>,
|
||||
}
|
||||
impl<T> Readable<T> for CollectionSelection<T> {}
|
||||
impl<T> Writeable<T> for CollectionSelection<T> {}
|
||||
|
||||
// =================
|
||||
// Selectors
|
||||
|
@ -125,22 +126,26 @@ mod hooks {
|
|||
|
||||
pub fn use_set_state<'a, T: PartialEq>(
|
||||
c: Context<'a>,
|
||||
t: &'static impl Writeable<T>,
|
||||
t: &impl Writeable<T>,
|
||||
) -> &'a Rc<dyn Fn(T)> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn use_recoil_state<'a, T: PartialEq + 'static>(
|
||||
ctx: Context<'a>,
|
||||
readable: &'static impl Writeable<T>,
|
||||
writeable: &impl Writeable<T>,
|
||||
) -> (&'a T, &'a Rc<dyn Fn(T)>) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn use_recoil_value<'a, T: PartialEq>(
|
||||
pub fn use_recoil_value<'a, T: PartialEq>(ctx: Context<'a>, t: &impl Readable<T>) -> &'a T {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn use_recoil_family<'a, K, V, C: FamilyCollection<K, V>>(
|
||||
ctx: Context<'a>,
|
||||
t: &'static impl Readable<T>,
|
||||
) -> &'a T {
|
||||
t: &AtomFamily<K, V, C>,
|
||||
) -> &'a C {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
|
|
@ -13,16 +13,24 @@ use recoil::*;
|
|||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
const APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum FilterState {
|
||||
All,
|
||||
Active,
|
||||
Completed,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App));
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct TodoItem {
|
||||
pub id: Uuid,
|
||||
pub checked: bool,
|
||||
pub contents: String,
|
||||
}
|
||||
|
||||
// Declare our global app state
|
||||
const TODO_LIST: Atom<HashMap<Uuid, TodoItem>> = atom(|_| Default::default());
|
||||
const FILTER: Atom<FilterState> = atom(|_| FilterState::All);
|
||||
const TODOS_LEFT: selector<usize> = selector(|api| api.get(&TODO_LIST).len());
|
||||
const TODO_LIST: Atom<HashMap<Uuid, TodoItem>> = |_| Default::default();
|
||||
const FILTER: Atom<FilterState> = |_| FilterState::All;
|
||||
const TODOS_LEFT: Selector<usize> = |api| api.get(&TODO_LIST).len();
|
||||
|
||||
// Implement a simple abstraction over sets/gets of multiple atoms
|
||||
struct TodoManager(RecoilApi);
|
||||
|
@ -64,32 +72,7 @@ impl TodoManager {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum FilterState {
|
||||
All,
|
||||
Active,
|
||||
Completed,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct TodoItem {
|
||||
pub id: Uuid,
|
||||
pub checked: bool,
|
||||
pub contents: String,
|
||||
}
|
||||
|
||||
fn App(ctx: Context, props: &()) -> DomTree {
|
||||
use_init_recoil_root(ctx);
|
||||
|
||||
rsx! { in ctx,
|
||||
div { id: "app", style { "{APP_STYLE}" }
|
||||
TodoList {}
|
||||
Footer {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn TodoList(ctx: Context, props: &()) -> DomTree {
|
||||
pub fn TodoList(ctx: Context, _props: &()) -> DomTree {
|
||||
let draft = use_state_new(&ctx, || "".to_string());
|
||||
let todos = use_recoil_value(&ctx, &TODO_LIST);
|
||||
let filter = use_recoil_value(&ctx, &FILTER);
|
||||
|
@ -154,9 +137,9 @@ pub fn TodoEntry(ctx: Context, props: &TodoEntryProps) -> DomTree {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
|
||||
let reducer = use_recoil_context::<TodoManager>(ctx);
|
||||
let items_left = use_selector(ctx, &TODOS_LEFT);
|
||||
pub fn FilterToggles(ctx: Context, _props: &()) -> DomTree {
|
||||
let reducer = use_recoil_callback(ctx, |api| TodoManager(api));
|
||||
let items_left = use_recoil_value(ctx, &TODOS_LEFT);
|
||||
|
||||
let toggles = [
|
||||
("All", "", FilterState::All),
|
||||
|
@ -168,10 +151,9 @@ pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
|
|||
rsx!(
|
||||
li {
|
||||
class: "{name}"
|
||||
a {
|
||||
a { "{name}",
|
||||
href: "{path}",
|
||||
onclick: move |_| reducer.set_filter(&filter),
|
||||
"{name}"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -196,7 +178,7 @@ pub fn FilterToggles(ctx: Context, props: &()) -> DomTree {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn Footer(ctx: Context, props: &()) -> DomTree {
|
||||
pub fn Footer(ctx: Context, _props: &()) -> DomTree {
|
||||
rsx! { in ctx,
|
||||
footer {
|
||||
class: "info"
|
||||
|
@ -212,3 +194,19 @@ pub fn Footer(ctx: Context, props: &()) -> DomTree {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
const APP_STYLE: &'static str = include_str!("./todomvc/style.css");
|
||||
|
||||
fn App(ctx: Context, _props: &()) -> DomTree {
|
||||
use_init_recoil_root(ctx);
|
||||
rsx! { in ctx,
|
||||
div { id: "app", style { "{APP_STYLE}" }
|
||||
TodoList {}
|
||||
Footer {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
wasm_bindgen_futures::spawn_local(dioxus_web::WebsysRenderer::start(App));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue