Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite router more #1860

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 48 additions & 30 deletions examples/router/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::rc::Rc;

use yew::prelude::*;
use yew_router::prelude::*;
use yew_router::{prelude::*, router::RouterListener};

mod components;
mod content;
Expand All @@ -15,34 +17,50 @@ pub enum Route {
#[at("/posts/:id")]
Post { id: u64 },
#[at("/posts")]
Posts,
Posts {
#[bind(query_arg = "p")]
page: u64,
},
#[at("/authors/:id")]
Author { id: u64 },
#[at("/authors")]
Authors,
#[at("/")]
Home,
#[not_found]
#[at("/404")]
NotFound,
}

impl Default for Route {
fn default() -> Self {
Route::NotFound
}
}

pub enum Msg {
ToggleNavbar,
RouteChanged(Rc<Route>),
}

pub struct Model {
link: ComponentLink<Self>,
route: Rc<Route>,
navbar_active: bool,
_listener: RouterListener<Route>,
}
impl Component for Model {
type Message = Msg;
type Properties = ();

fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
let router = Router::new(link.clone());
let route = router.current();
let _listener = router.register(link.callback(Msg::RouteChanged));
Self {
link,
route,
navbar_active: false,
_listener,
}
}

Expand All @@ -52,6 +70,10 @@ impl Component for Model {
self.navbar_active = !self.navbar_active;
true
}
Msg::RouteChanged(route) => {
self.route = route;
true
}
}
}

Expand All @@ -64,9 +86,28 @@ impl Component for Model {
<>
{ self.view_nav() }

<main>
<Router<Route> render=Router::render(switch) />
</main>
<main>{
match &*self.route {
Route::Post { id } => {
html! { <Post seed=*id /> }
}
Route::Posts { page } => {
html! { <PostList page=*page /> }
}
Route::Author { id } => {
html! { <Author seed=*id /> }
}
Route::Authors => {
html! { <AuthorList /> }
}
Route::Home => {
html! { <Home /> }
}
Route::NotFound => {
html! { <PageNotFound /> }
}
}
}</main>
<footer class="footer">
<div class="content has-text-centered">
{ "Powered by " }
Expand Down Expand Up @@ -111,7 +152,7 @@ impl Model {
<Link<Route> classes=classes!("navbar-item") route=Route::Home>
{ "Home" }
</Link<Route>>
<Link<Route> classes=classes!("navbar-item") route=Route::Posts>
<Link<Route> classes=classes!("navbar-item") route=Route::Posts { page: 1 }>
{ "Posts" }
</Link<Route>>

Expand All @@ -134,29 +175,6 @@ impl Model {
}
}

fn switch(routes: &Route) -> Html {
match routes {
Route::Post { id } => {
html! { <Post seed=*id /> }
}
Route::Posts => {
html! { <PostList /> }
}
Route::Author { id } => {
html! { <Author seed=*id /> }
}
Route::Authors => {
html! { <AuthorList /> }
}
Route::Home => {
html! { <Home /> }
}
Route::NotFound => {
html! { <PageNotFound /> }
}
}
}

fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Trace));
yew::start_app::<Model>();
Expand Down
54 changes: 22 additions & 32 deletions examples/router/src/pages/post_list.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,60 @@
use crate::components::{pagination::Pagination, post_card::PostCard};
use crate::Route;
use serde::{Deserialize, Serialize};
use yew::prelude::*;
use yew_router::{Router, RouterAction};

const ITEMS_PER_PAGE: u64 = 10;
const TOTAL_PAGES: u64 = u64::MAX / ITEMS_PER_PAGE;

pub enum Msg {
ShowPage(u64),
}

#[derive(Serialize, Deserialize)]
struct PageQuery {
page: u64,
#[derive(Properties, Clone)]
pub struct PostListProps {
pub page: u64,
}

pub struct PostList {
link: ComponentLink<Self>,
router: Router<crate::Route>,
props: PostListProps,
}
impl Component for PostList {
type Message = Msg;
type Properties = ();
type Message = ();
type Properties = PostListProps;

fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self {
Self { link }
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
let router = Router::new(link);
Self { router, props }
}

fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::ShowPage(page) => {
yew_router::push_route_with_query(Route::Posts, PageQuery { page }).unwrap();
true
}
}
fn update(&mut self, _msg: Self::Message) -> ShouldRender {
false
}

fn change(&mut self, _props: Self::Properties) -> ShouldRender {
false
fn change(&mut self, props: Self::Properties) -> ShouldRender {
self.props = props;
true
}

fn view(&self) -> Html {
let page = self.current_page();
let on_switch_page = self
.router
.dispatcher(|page| Some(RouterAction::Push(Route::Posts { page })));

html! {
<div class="section container">
<h1 class="title">{ "Posts" }</h1>
<h2 class="subtitle">{ "All of our quality writing in one place" }</h2>
{ self.view_posts() }
<Pagination
page=page
page=self.props.page
total_pages=TOTAL_PAGES
on_switch_page=self.link.callback(Msg::ShowPage)
on_switch_page=on_switch_page
/>
</div>
}
}
}
impl PostList {
fn view_posts(&self) -> Html {
let start_seed = (self.current_page() - 1) * ITEMS_PER_PAGE;
let start_seed = (self.props.page - 1) * ITEMS_PER_PAGE;
let mut cards = (0..ITEMS_PER_PAGE).map(|seed_offset| {
html! {
<li class="list-item mb-5">
Expand All @@ -81,10 +77,4 @@ impl PostList {
</div>
}
}

fn current_page(&self) -> u64 {
yew_router::parse_query::<PageQuery>()
.map(|it| it.page)
.unwrap_or(1)
}
}
24 changes: 12 additions & 12 deletions packages/yew-functional/src/hooks/use_context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{get_current_scope, use_hook};
use yew::context::ContextHandle;
use yew::{
context::{Context, ContextListener},
Callback,
};

/// Hook for consuming context values in function components.
/// The context of the type passed as `T` is returned. If there is no such context in scope, `None` is returned.
Expand Down Expand Up @@ -32,7 +35,7 @@ use yew::context::ContextHandle;
pub fn use_context<T: Clone + PartialEq + 'static>() -> Option<T> {
struct UseContextState<T2: Clone + PartialEq + 'static> {
initialized: bool,
context: Option<(T2, ContextHandle<T2>)>,
context: Option<(Context<T2>, ContextListener<T2>)>,
}

let scope = get_current_scope()
Expand All @@ -46,18 +49,15 @@ pub fn use_context<T: Clone + PartialEq + 'static>() -> Option<T> {
|state: &mut UseContextState<T>, updater| {
if !state.initialized {
state.initialized = true;
let callback = move |ctx: T| {
updater.callback(|state: &mut UseContextState<T>| {
if let Some(context) = &mut state.context {
context.0 = ctx;
}
true
});
};
state.context = scope.context::<T>(callback.into());
if let Some(context) = scope.context::<T>() {
let listener = context.register(Callback::from(move |_| {
updater.callback(|_: &mut UseContextState<T>| true);
}));
state.context = Some((context, listener));
}
}

Some(state.context.as_ref()?.0.clone())
Some(state.context.as_ref()?.0.current())
},
|state| {
state.context = None;
Expand Down
2 changes: 1 addition & 1 deletion packages/yew-functional/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ where
}
}

pub(crate) fn get_current_scope() -> Option<AnyScope> {
pub fn get_current_scope() -> Option<AnyScope> {
if CURRENT_HOOK.is_set() {
Some(CURRENT_HOOK.with(|state| state.scope.clone()))
} else {
Expand Down
3 changes: 2 additions & 1 deletion packages/yew-router-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ proc-macro = true
heck = "0.3.2"
proc-macro2 = "1.0.24"
quote = "1.0.9"
syn = { version = "1.0.64", features = ["full","extra-traits"] }
syn = { version = "1.0.64", features = ["full", "extra-traits"] }
regex = "1.5.4"

[dev-dependencies]
rustversion = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/yew-router-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use syn::parse_macro_input;
/// NotFound,
/// }
/// ```
#[proc_macro_derive(Routable, attributes(at, not_found))]
#[proc_macro_derive(Routable, attributes(at, bind))]
pub fn routable_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as Routable);
routable_derive_impl(input).into()
Expand Down
Loading