freya_core/hooks/
use_id.rs

1use std::marker::PhantomData;
2
3use crate::{
4    prelude::{
5        State,
6        provide_context_for_scope_id,
7        try_consume_context,
8        use_hook,
9    },
10    scope_id::ScopeId,
11};
12
13pub struct UseId<T> {
14    counter: State<usize>,
15    _phantom: PhantomData<T>,
16}
17
18impl<T> Clone for UseId<T> {
19    fn clone(&self) -> Self {
20        *self
21    }
22}
23
24impl<T> Copy for UseId<T> {}
25
26impl<T: 'static> UseId<T> {
27    /// Composable alternative to [use_id].
28    pub fn get_in_hook() -> usize {
29        let mut storage = match try_consume_context::<UseId<T>>() {
30            Some(storage) => storage,
31            None => {
32                let use_id = UseId {
33                    counter: State::create_in_scope(0, Some(ScopeId::ROOT)),
34                    _phantom: PhantomData::<T>,
35                };
36                provide_context_for_scope_id(use_id, ScopeId::ROOT);
37                use_id
38            }
39        };
40        *storage.counter.write() += 1;
41        *storage.counter.peek()
42    }
43}
44
45/// Get a unique for a given generic type.
46///
47/// Every component using this hook will get a different ID.
48///
49/// The ID does not change in between renders.
50///
51/// To use it inside other hooks check [UseId::get_in_hook]
52pub fn use_id<T: 'static>() -> usize {
53    use_hook(UseId::<T>::get_in_hook)
54}