I have a spreadsheet application and I want to build a simple UI for it in the web. I have tried to build a simple prototype but I do not understand how I should handle partial re-renders. When a cell is changed some of the cells in the app should change, however re rendering every cell takes really long (To test this I tried a 500x500 grid). My guess would be to use the use memo hook maybe but I do not understand how to use it. This is a simple question but I have trouble understanding this so help would be apprenticed. Here is my prototype:
use std::collections::HashMap;
use yew::prelude::*;
use crate::{common_types::Index, spreadsheet::SpreadSheet};
#[derive(Properties, PartialEq)]
struct CellProps {
pub row: usize,
pub col: usize,
pub text: String,
pub on_click: Callback<(usize, usize)>,
}
struct Cell;
impl Component for Cell {
type Message = ();
type Properties = CellProps;
fn create(_ctx: &Context<Self>) -> Self {
Self
}
fn view(&self, ctx: &Context<Self>) -> Html {
let row = ctx.props().row;
let col = ctx.props().col;
let text = ctx.props().text.clone();
let on_click = ctx.props().on_click.clone();
let onclick = Callback::from(move |_| on_click.emit((row, col)));
html! {
<div
onclick={onclick}
style="border: 1px solid black; padding: 10px; text-align: center; cursor: pointer;"
>
{ text }
</div>
}
}
}
pub struct Grid {
cell_data: SpreadSheet,
}
pub enum Msg {
CellClicked(usize, usize),
}
impl Component for Grid {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self { cell_data: SpreadSheet::default() }
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::CellClicked(row, col) => {
self.cell_data.add_cell_and_compute(Index{ x: col, y: row }, "Clicked!".to_string());
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<div style="display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px;">
{
(0..500).flat_map(|row| {
(0..500).map(move |col| {
let text = self.cell_data.get_text(Index { x: col, y: row });
let on_click = ctx.link().callback(move |_| Msg::CellClicked(row, col));
html! {
<Cell
row={row}
col={col}
text={text}
on_click={on_click}
/>
}
})
}).collect::<Html>()
}
</div>
}
}
}