10 releases
0.3.0 | May 30, 2023 |
---|---|
0.2.0 | Jul 1, 2022 |
0.1.8 | Apr 28, 2022 |
0.1.7 | Sep 28, 2021 |
0.1.4 | Jul 28, 2021 |
#25 in #frontend
Used in percy-preview-app
14KB
112 lines
app-world
A framework agnostic approach to managing frontend application state.
Overview
app-world
is simple thread-safe state management library that is designed to be useful in cross-platform frontend applications
that manage large amounts of application state.
With app-world
you have a single World
which holds your application State
, as well your application's Resource
s.
Resource
s are used to interface with the outside world, such as to write to a local file storage or to make an API request.
The only way to mutate application state is by sending a Msg
(ignoring UnsafeCell
based interior mutability).
This means that all state mutation can be handled in a single place, which makes it easy to reason about the application's behavior and decreases the likelihood of code duplication.
Cross-Platform Applications
app-world
does not have any platform dependent code, making it suitable for writing cross-platform application logic that can run on the
web, mobile and desktop.
For example, app-world
can be used to manage state in a Rust core application that gets run on iOS
, Android
and in web browsers.
Thread Safety
You cannot acquire a write guard on the World directly. The only way to write to a World is via AppWorld::msg
.
Multiple threads can read from an AppWorld
simultaneously, but only one AppWorld::msg
will be processed at a time.
This means that you can safely use app-world
in multi-threaded applications without worrying about deadlocks.
Games
Multiple threads can read from an AppWorld
simultaneously, but only one AppWorld::msg
will be processed at a time.
This makes app-world
a poor fit for games that have hardcore performance requirements where you might want many threads to be able to manipulate the World simultaneously.
In those cases, consider using one of the many existing Entity Component System crates.
Example Usage
use app_world::AppWorldWrapper;
struct MyAppWorld {
state: MyAppState,
resources: MyAppResources,
}
struct MyAppState {
count: u32
}
struct MyAppResources {
api_client: Arc<dyn SomeApiClient>
}
enum Msg {
IncrementCount(u8)
}
type MyAppStateWrapper = AppWorldWrapper<MyAppState>;
impl AppWorld for MyAppWorld {
type Msg = Msg;
fn msg(&mut self, message: Msg) {
match msg {
Msg::IncrementCount(increment) => {
self.count += 1;
}
}
}
}
fn main () {
let world = AppWorldWrapper::new(MyAppWorld::new());
let world_clone = world.clone();
assert_eq!(world.read().count, 0);
world.msg(Msg::IncrementCount);
world_clone.msg(Msg::IncrementCount);
assert_eq!(world.read().count, 2);
}
Inspiration
-
The Elm Architecture for the decoupling of views and application state.
-
specs for the
World
State
andResource
names.