I'm having trouble working with Rc and RefCell.
I would like to be able to
Call the child's render method from the parent.
Be able to update either structs "count" member using the set_state method implemented for each struct. The code that executes the set_state will be run async by a rust wasm event handler so the closure needs to have access to a mutable reference to the struct itself.
use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug, Default, Clone)]
pub struct Main {
pub child: Rc<RefCell<MainChild>>,
pub count: i32,
}
impl Main {
pub fn create() -> Rc<RefCell<Self>> {
let main = Main {
child: MainChild::create(),
count: 0,
};
Rc::new(RefCell::new(main))
}
pub fn set_state(&mut self, new_count: i32) {
use std::borrow::BorrowMut;
self.borrow_mut().count += new_count;
self.borrow_mut().render();
}
pub fn render(&mut self) {
use std::borrow::BorrowMut;
let clone = Rc::clone(self.borrow_mut());
// This closure will be executed by an event handler in rust wasm but I left that code out for //simplicity.
let closure = Box::new(move || clone.set_state(2));
self.borrow_mut().child.borrow_mut().render();
// render something that displays self.count
}
}
#[derive(Debug, Default, Clone)]
pub struct MainChild {
pub count: i32,
}
impl MainChild {
pub fn create() -> Rc<RefCell<Self>> {
let child = MainChild { count: 0 };
Rc::new(RefCell::new(child))
}
pub fn set_state(&mut self, new_count: i32) {
use std::borrow::BorrowMut;
self.borrow_mut().count += new_count;
self.borrow_mut().render();
}
pub fn render(&mut self) {
// render something that displays self.count
}
}
pub fn main() {
let main = Main::create();
main.borrow_mut().render();
}
I get multiple errors indicating the struct's implemented methods cannot be found.
--> src/main.rs:29:31
|
29 | let clone = Rc::clone(self.borrow_mut());
| ^^^^^^^^^^^^^^^^^ expected struct `std::rc::Rc`, found struct `Main`
|
= note: expected reference `&std::rc::Rc<_>`
found mutable reference `&mut Main`
error[E0599]: no method named `set_state` found for struct `std::rc::Rc<_>` in the current scope
--> src/main.rs:30:46
|
30 |
error[E0599]: no method named `render` found for mutable reference `&mut std::rc::Rc<std::cell::RefCell<MainChild>>` in the current scope
--> src/main.rs:31:46
|
31 | self.borrow_mut().child.borrow_mut().render();
| ^^^^^^ method not found in `&mut std::rc::Rc<std::cell::RefCell<MainChild>>`
Rc::clone can only clone the outer Rc wrapper type, not the cell inside it, and not the temporary proxy object that borrow_mut() returns. Rc::clone(self) should work.
So one issue is that within Main's render self is not equal to Rc<RefCell<Self>> but is instead equal to the struct Main. This makes sense to me now. It does throw a wrench in my plans of passing.a Rc::clone of self to a closure from within Main's render method.
The second issue persists. self.child.borrow_mut() does not give me MainChild but instead RefCell { value: MainChild { count: 0 } }. It's like I cannot get the value from inside the RefCell for some reason
This looks promising. I'm working on implementing this into the actual code. One obstacle is that render and create already belong to a "Component" trait (did not post that part of the code).