# Usage
## Create a Connection
To connect to a database use the `use_surreal_login` hook. The hook returns a token that has to be used in a `` context provider.
```rust
#[function_component]
fn MyComponent(props: &P) -> Html{
let login = Database {
username: "user",
password: "user",
database: "test",
namespace: "test"
};
let token = use_surreal_login("localhost:8000".to_owned(), login);
html! {
// Your App goes here
}
}
```
The `` will suspend your app until the login was successful.
## Query Components
A `` component will retrieve all database entries matching the given query and display them one after the other
```rust
html! {
selector="select * from myTable"/>
}
```
`/>` has four properties
- `selector`: Something that can be turned into a `SelectStatement`, this includes `String`s and surreal records (`Thing`s in the surreal source code)
- `parameters` (Optional): a Vec of `(String, String)` touples that will be bound to the query
- `filter` (Optional): a yew callback `Fn(T::Properties) -> bool` used for local filtering.
- `fallback` (Optional): an `Html` element that will be rendered while the data is being fetched (uses yew Suspension under the hood).
`` stores the result of the query in an internally managed state. If you want to manipulat the state or use the same query result in multiple places you will have to use `` in combination with the `use_query_state` hook
```rust
let list_state = use_query_state::("SELECT * FROM item");
html!{
state={list_state}/>
}
```
Because the state is externally managed the `` component has no `selector` and `parameters` field.
### Properties
In order for the component `` to be rendered by `` `Inner::Properties` needs to derive `SurrealProps` (in addition to `Properties`, `PartialEq` and `Clone`)
```rust
#[derive(SurrealProps, Properties, PartialEq, Clone)]
struct InnerProps {
#[id] id: Option,
name: AttrValue,
}
#[function_component]
fn Inner(props: &InnerProps) -> Html{
// You know what to do here
}
```
The component's `id` property can be an `ID` or an `Option`, if you want to create new database entries from the components you should choose `Option` so you can set the id to `None` on new entries.
### Local Properties
To add properties that can be set locally instead of retrieved from the server, mark them as `#[local]`
```rust
#[derive(SurrealProps, Properties, PartialEq, Clone)]
struct InnerProps {
id: AttrValue,
name: AttrValue,
#[local]
color: AttrValue
}
```
They will need to be set on the Wrapper Component and apply to all `Inner` components
```rust
selector="select * from myTable" color="red"/>
```
### ForeignKeys
There are two ways to deal with foreign keys:
A) Use a property of type `ForeignKey` (this is just an alias of `ID` but more readable)
B) Use a property of type `StaticChild` where `T` is a deserializable struct. This allows for the data to be retrieved in one go with the `FETCH` keyword but will only write the id of the fetched data to surreal when updated/created
## "Raw" Database access
Instead of rendering Components directly with a `` you can use the `use_surreal()` hook to:
- `select`: fetch arbitrary data from surreal using a `Selector`
- `update`: update a components underlying data (local and remote). This always uses the `MERGE` mode since there is no guarantee that the local struct contains all fields of the remote table.
- `create`: create a new database entry and use convinience methods to store the new entry locally
- `query`: Execute an arbitrary SQL query and store the results
```rust
use_surreal().create(
"item".to_owned(),
ToDoItemPropsRemote {
done: false,
// Note how having the type of id be Option
// enables you to delegate id creation to the Database
id: None,
text: None,
title: "Test".into(),
img: None
},
).execute();
```
### Self Refs
The `use_surreal().update()` method takes a `SurrealSelfRef` as its argument, this can be obtained from inside a component by using the hook `use_self_ref()`.
When the update is executed the data returned from the database will be used to replace the properties of the component iff the new data still matches the original selector, otherwise the data is dropped from local storage.
**Note:** It is highly recomended to use the `use_update_callback` hook when creating self-updating components.