quickrenard v2.8.3
π¦quickrenardπ¦
π¦Quick Renardλ₯Ό μ μνμ΅λλ€.π¦
1. μ μ λ° μ€κ³
- 쿼리 κΈ°λ°μ μν μ μ: κ° μνλ₯Ό GraphQL μ€ν€λ§μ²λΌ μ μν©λλ€. μλ₯Ό λ€μ΄, μνμ νμ , μ΄κΈ° κ°, μμ‘΄μ± λ±μ λͺ μμ μΌλ‘ ννν©λλ€.
- 쿼리 λ° λ³μ΄ μμ±: μ¬μ©μκ° μνλ₯Ό μ‘°ννκ±°λ μμ ν μ μλλ‘ μΏΌλ¦¬μ λ³μ΄λ₯Ό μ 곡ν©λλ€.
2. λΌμ΄λΈλ¬λ¦¬ ꡬν
- μν μ μ₯μ: λͺ¨λ μνλ₯Ό μ μ₯νλ μ€μ μ μ₯μλ₯Ό λ§λλλ€.
- 쿼리 ν΄μκΈ°: μ£Όμ΄μ§ 쿼리λ₯Ό ν΄μνκ³ ν΄λΉνλ μνλ₯Ό λ°ννλ λ‘μ§μ ꡬνν©λλ€.
- λ³μ΄(Mutation) μ²λ¦¬κΈ°: μ£Όμ΄μ§ λ³μ΄(Mutation)λ₯Ό ν΄μνκ³ μνλ₯Ό μ λ°μ΄νΈνλ λ‘μ§μ ꡬνν©λλ€.
- ꡬλ (subscription) λ©μ»€λμ¦: νΉμ μνμ λ³μ΄λ₯Ό ꡬλ (subscription)νκ³ , λ³μ΄κ° κ°μ§λλ©΄ μ½λ°±μ μ€ννλ λ©μ»€λμ¦μ ꡬνν©λλ€.
3. React Hooks
- useStateQuery: μ£Όμ΄μ§ 쿼리μ ν΄λΉνλ μνλ₯Ό λ°ννλ Hookμ μ 곡ν©λλ€.
- useStateMutation: μ£Όμ΄μ§ λ³μ΄λ₯Ό μ€ννλ ν¨μμ μνλ₯Ό λ°ννλ Hookμ μ 곡ν©λλ€.
- useStateSubscription: μ£Όμ΄μ§ μνμ λ³νλ₯Ό ꡬλ νκ³ , λ³νκ° κ°μ§λλ©΄ μ»΄ν¬λνΈλ₯Ό 리λ λλ§νλ Hookμ μ 곡ν©λλ€.
- μ¬μ©μλ 쿼리μ λ³μ΄λ₯Ό μ¬μ©νμ¬ μνμ μ½κ² μ κ·Όνκ³ μμ ν μ μμΌλ©°,
- νμν μνμ λ³νλ§μ ꡬλ νμ¬ μ»΄ν¬λνΈλ₯Ό 리λ λλ§ν μ μκ² λ©λλ€.
1. μν μ μ₯μ (stateStore):
- Quick Renard λΌμ΄λΈλ¬λ¦¬μμλ μ μμ μΌλ‘ κ΄λ¦¬λλ stateStoreλΌλ μ€μ μ μ₯μλ₯Ό ν΅ν΄ μνλ₯Ό κ΄λ¦¬ν©λλ€. μ΄ μ μ₯μμλ μ ν리μΌμ΄μ μ λͺ¨λ μνκ° μ μ₯λλ©°, 쿼리 κΈ°λ°μ μ κ·Ό λ°©μμ μ¬μ©νμ¬ νΉμ μνλ₯Ό κ²μνκ±°λ μμ ν μ μμ΅λλ€.
2. μν μ€ν€λ§ (StateSchema):
- μνμ ꡬ쑰μ κΈ°λλλ νμ , κΈ°λ³Έκ° λ±μ μ μνκΈ° μν΄ μ€ν€λ§λ₯Ό μ¬μ©ν©λλ€. μ΄λ₯Ό ν΅ν΄ μνμ μ΄κΈ° μ€μ μ μ½κ² ν μ μμΌλ©°, μν λ³κ²½ μ μ ν¨μ± κ²μ¬μ κΈ°μ€μΌλ‘ μ¬μ©λ©λλ€.
3. μν λ³μ΄ (setStateMutation):
- μ΄ ν¨μλ₯Ό ν΅ν΄ μνλ₯Ό μμ νκ² λ©λλ€. ν¨μ λ΄λΆμμλ μ€ν€λ§λ₯Ό λ°νμΌλ‘ μνμ μ ν¨μ± κ²μ¬λ₯Ό μνν μ μμΌλ©°, ν΄λΉ μνμ λ³νκ° μμ κ²½μ°, κ·Έ μνλ₯Ό ꡬλ νκ³ μλ λͺ¨λ ꡬλ μλ€μκ² μλ¦Όμ 보λ λλ€.
4. μν ꡬλ (subscribeStateChange):
- νΉμ μνμ λ³νλ₯Ό κ΄μ°°νκ³ μ νλ μ»΄ν¬λνΈλ μ΄ ν¨μλ₯Ό ν΅ν΄ ν΄λΉ μνμ λ³νλ₯Ό ꡬλ ν©λλ€. μνκ° λ³κ²½λ λλ§λ€ ꡬλ νκ³ μλ μ»΄ν¬λνΈλ μ½λ°± ν¨μλ₯Ό μ€ννκ² λ©λλ€. μ΄λ₯Ό ν΅ν΄ μν λ³νμ λ°λ₯Έ 리λ λλ§μ΄λ λ€λ₯Έ μμ μ μνν μ μμ΅λλ€.
π¦Ver 1.2.0π¦
νμ κ²μ¦ λ‘μ§ μΆκ°
1. Enum κ²μ¦:
- enum ν€λ₯Ό ν΅ν΄ νμ©λ λ¬Έμμ΄ μ§ν©μ μ μν μ μμ΅λλ€.
- ν΄λΉ κ°μ΄ enumμ μ μλ λ¬Έμμ΄ μ€ νλμΈμ§ κ²μ¬ν©λλ€.
- μλ₯Ό λ€μ΄, μνκ° νΉμ λ¬Έμμ΄ κ°λ€ μ€ νλλ§ κ°μ ΈμΌ ν κ²½μ° μ¬μ©λ©λλ€.
2. κ°μ²΄ μμ± κ²μ¦:
- properties ν€λ₯Ό ν΅ν΄ κ°μ²΄μ κ° μμ±μ λν μ€ν€λ§λ₯Ό μ μν μ μμ΅λλ€.
- κ° μμ±μ μ νμ κ²μ¬νμ¬ ν΄λΉ μμ±μ΄ μ¬λ°λ₯Έ μ νμΈμ§ νμΈν©λλ€.
- κ°μ²΄ λ΄λΆμ κ° μμ±μ΄ μ μλ μ€ν€λ§λ₯Ό λ°λ₯΄λμ§ κ²μ¬νκΈ° μν΄ μ¬μ©λ©λλ€.
3. λ°°μ΄ νλͺ© νμ κ²μ¦:
- λ°°μ΄μ λͺ¨λ νλͺ©μ΄ ν΄λΉ μ€ν€λ§λ₯Ό μ€μνλμ§ κ²μ¬ν©λλ€.
- λ°°μ΄ λ΄λΆμ κ° νλͺ©μ΄ μ μλ μ€ν€λ§λ₯Ό λ°λ₯΄λμ§ κ²μ¬νκΈ° μν΄ μ¬μ©λ©λλ€.
π¦Ver 2.0.0π¦
ν¨μ μ μ κ΄λ¦¬μ functionStore μΆκ°
1. κ΄λ¦¬ν μ μλ λνμ μΈ ν¨μ μ ν:
μμ ν¨μ: λμΌν μΈμμ λν΄ νμ λμΌν κ²°κ³Όλ₯Ό λ°ννκ³ , μΈλΆ μνλ₯Ό λ³κ²½νμ§ μλ ν¨μμ λλ€.
μ νΈλ¦¬ν° ν¨μ: λ¬Έμμ΄ μ²λ¦¬, λ μ§ κ³μ°, μ«μ ν¬λ§·ν λ± μ¬μ¬μ© κ°λ₯ν κΈ°λ₯μ μ 곡ν©λλ€.
ν¬νΌ ν¨μ: λ°λ³΅μ μΌλ‘ μ¬μ©λλ λ‘μ§μ μΆμνν ν¨μμ λλ€ (μ: API μμ²).
2. μμ κ°μ ν¨μλ€μ κ΄λ¦¬ν μ μμΌλ, μ£Όμκ° νμν©λλ€:
- μ¬μ΄λ μ΄ννΈ: ν¨μκ° μΈλΆ μμ€ν μ μνμ μν₯μ μ£Όκ±°λ κ·Έλ‘λΆν° μν₯μ λ°λ κ²½μ°, (μμ: λ°μ΄ν°λ² μ΄μ€μ μ κ·Όνκ±°λ μΈλΆ APIλ₯Ό νΈμΆνλ ν¨μ) μμΈ‘νμ§ λͺ»ν κ²°κ³Όλ₯Ό μ΄λν μ μμ΅λλ€.
μν μμ‘΄μ±: ν¨μκ° λ΄λΆ μνμ μμ‘΄νλ κ²½μ°, κ·Έ μνμ λ³νκ° ν¨μμ κ²°κ³Όμ μν₯μ μ€ μ μμ΅λλ€.
μ€μ½νμ ν΄λ‘μ : ν¨μκ° νΉμ μ€μ½νμ λ³μλ₯Ό μ¬μ©νλ κ²½μ°, μ΄λ¬ν μμ‘΄μ±μ κ΄λ¦¬ν΄μΌ ν©λλ€.
λμμ± μ μ΄: μ¬λ¬ ꡬλ μκ° λμΌν ν¨μμ κ²°κ³Όλ₯Ό ꡬλ ν λ λ°μνλ λμμ± μ΄μλ₯Ό κ΄λ¦¬ν΄μΌ ν©λλ€.
p.s: QuickRenard 2.1.0 λ²μ μμλ ν¨μ νΈμΆμ λμνλ ꡬλ κ³Ό ꡬλ μ·¨μ κ³Όμ μ΄ λΌμ΄λΈλ¬λ¦¬ λ΄λΆμ μΌλ‘ μλμΌλ‘ κ΄λ¦¬λλλ‘ κ°μ νμμ΅λλ€. κ°λ¨ν λ§ν΄, QuickRenardκ° κ΅¬λ κ³Ό ꡬλ μ·¨μμ μΈμΈν κ΄λ¦¬λ₯Ό μλνν¨μΌλ‘μ¨, κ°λ°μλ ν¨μ λ±λ‘ λ° νΈμΆμ μ§μ€ν μ μμΌλ©°, λ μμ μ μ΄κ³ μ μ§λ³΄μκ° μ¬μ΄ μ½λλ₯Ό μμ±ν μ μμ κ²μ λλ€.
functionStoreλ₯Ό μ¬μ©νλ €λ©΄, μλμ !!! How to use !!! λ₯Ό μ°Έμ‘°νμΈμ.
π¦Ver 2.3.0 - Ver 2.5.0π¦
μν μΊμ± λ‘μ§ μΆκ°:
μ±λ₯ μ΅μ νλ₯Ό μν μλ‘μ΄ κΈ°λ₯:
μν μΊμ±μ ν΅ν΄, μμ£Ό μ κ·Όνλ μνμ λν μ μν κ²μμ΄ κ°λ₯ν©λλ€. λΌμ΄λΈλ¬λ¦¬ μ¬μ© μ, μ±λ₯μ΄ μ λ°μ μΌλ‘ κ°μ λ κ²μ λλ€.
μ΄μ μ μμ²λ μν κ°μ μΊμμ μ μ₯ν©λλ€. κ°μ μνλ₯Ό λ€μ μμ²ν λ μ μν μλ΅μ λ°μ μ μμ΅λλ€. 볡μ‘ν κ³μ° νΉμ λ°μ΄ν°λ² μ΄μ€ μΏΌλ¦¬κ° νμν μνμ κ²½μ°, νΉν μ΄ κΈ°λ₯μ μ μ©ν κ²μ λλ€.
λ€νΈμν¬ μ§μ°, μλ² κ³ΌλΆνλ₯Ό μλ°©νλ λ°μ ν¨κ³Όμ μ λλ€. μ격 λ°μ΄ν°λ₯Ό μνλ‘ κ΄λ¦¬νλ κ²½μ°, μΊμ±μ λ€νΈμν¬ μμ² μλ₯Ό μ€μμΌλ‘μ¨, λ°μ΄ν° μ μ‘μ ν¨μ¨μ μΌλ‘ μνν μ μμ΅λλ€.
μΊμ± κ΄λ ¨ μ£Όμμ¬ν:
μΊμλ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό μν΄, λν΄νΈ κ°μΌλ‘ 15λΆ λ€μ λ§λ£λ©λλ€.
Ver 2.5.0λΆν° μΊμ λ§λ£ μκ°μ μμλ‘ μ‘°μ ν μ μμ΅λλ€. λ°©λ² λ° μ£Όμμ¬νμ βββ How to use βββλ₯Ό μ°Έμ‘°νμΈμ.
μ λ°μ΄νΈλ₯Ό ν΅ν΄ QuickRenardλ μ ν리μΌμ΄μ μ μ±λ₯μ κ°μ νκ³ , λ³΄λ€ ν¨μ¨μ μΌλ‘ μν κ΄λ¦¬λ₯Ό ν μ μλλ‘ μ§μν©λλ€. Ver 2.3.0 μ λ°μ΄νΈλ νΉν λκ·λͺ¨ μ ν리μΌμ΄μ λ° λ°μ΄ν° μ§μ½μ μμ μ μ€μ μ λκ³ μ§ννμ΅λλ€.
π¦Ver 2.6.0 - Ver 2.7.0π¦
- μν κ΄λ¦¬ μμ€ν μ΄ λμ± κ°λ ₯ν΄μ‘μ΅λλ€. μ΄μ μν κ°μ 볡μ‘ν μ’ μμ±μ κ·Έλν νμ μκ³ λ¦¬μ¦μΌλ‘ ν¨κ³Όμ μΌλ‘ κ΄λ¦¬ν μ μμ΅λλ€. DFS(κΉμ΄ μ°μ νμ)μ BFS(λλΉ μ°μ νμ) μκ³ λ¦¬μ¦μ νμ©νμ¬, μνμ μ λ°μ΄νΈκ° λ€λ₯Έ μνμ λ―ΈμΉλ μν₯μ ν¨κ³Όμ μΌλ‘ μ²λ¦¬ν©λλ€.
- DFS(κΉμ΄ μ°μ νμ): κΉκ² μ°κ²°λ μν κ°μ μ’ μμ±μ νμν©λλ€. μ΄ λ°©μμ μν κ°μ κΉμ μ°κ²°μ΄ μλ κ²½μ°μ μ ν©ν©λλ€.
- BFS(λλΉ μ°μ νμ): λμ λ²μμ μν κ°μ μ’ μμ±μ νμν©λλ€. μ΄ λ°©μμ λ λμ λ²μμ μν κ° μν₯μ κ΄λ¦¬ν λ μ μ©ν©λλ€.
- Ver 2.7.0λΆν°λ μν κ°μ μ’ μμ±μ κ΄λ¦¬ν μ, updateStateν¨μκ° DFSλ‘ μ²λ¦¬ν μ§, BFSλ‘ μ²λ¦¬ν μ§ μλμΌλ‘ νλ³ν΄ μ€λλ€. μ΄λ₯Ό ν΅ν΄ μν κ΄λ¦¬κ° λμ± μ μ°νκ³ ν¨μ¨μ μΌλ‘ μ΄λ£¨μ΄μ§λλ€.
DFS λλ BFS κ΄λ ¨ μ€μ μ μ¬μ©νλ €λ©΄, μλμ βββ How to use βββ λ₯Ό μ°Έμ‘°νμΈμ.
π¦Ver 2.7.1 - π¦
- Lodashλ‘λΆν° λ 립νμ΅λλ€.
π¦Ver 2.8.1 - π¦
- μν κ΄λ¦¬ ν μ κ°ν λ° κΈ°λ₯ νμ₯
μ£Όμ λ³κ²½ μ¬ν:
useStateQuery κ°μ : Ver 2.8.0μμ useStateQueryλ μνμ λ‘λ© λ° μλ¬ μ²λ¦¬λ₯Ό λ³΄λ€ ν¨κ³Όμ μΌλ‘ κ΄λ¦¬ν©λλ€. λ°ν κ°μ²΄μλ data νλ μΈμλ loading λ° error νλκ° ν¬ν¨λμ΄ μμ΄, μν λ‘λ©μ μ§ν μν©κ³Ό λ°μν μ μλ μλ¬λ₯Ό μ½κ² μΆμ ν μ μμ΅λλ€. μ΄λ¬ν μΆκ° νλλ μν μ‘°ν κ³Όμ μμμ λ€μν μν©λ€μ μ ν리μΌμ΄μ λ΄μμ μΈμ¬νκ² μ²λ¦¬ν μ μκ² ν΄μ£Όμ΄, λ κ°λ ₯νκ³ μ μ°ν μν κ΄λ¦¬κ° κ°λ₯ν©λλ€.
useStateMutation νμ₯: μν λ³κ²½ λ‘μ§μ΄ λΉλκΈ°μ μΌλ‘ μ²λ¦¬λ μ μλλ‘ useStateMutationμ΄ κ°μ λμμ΅λλ€. μν λ³κ²½ μ λ‘λ© μνμ μ€λ₯ μ²λ¦¬λ₯Ό κ΄λ¦¬ν μ μλ κΈ°λ₯μ΄ μΆκ°λμμΌλ©°, μ΄λ API νΈμΆκ³Ό κ°μ λΉλκΈ° μμ μ λ§€μ° μ μ©ν©λλ€. μ¬μ©μλ μν λ³κ²½ ν¨μ(mutate), νμ¬ μν(state), λ‘λ© μν(loading), κ·Έλ¦¬κ³ λ°μν μ€λ₯(error)λ₯Ό μ½κ² κ΄λ¦¬ν μ μμ΅λλ€.
useStateSubscriptionμ μν λ³ν κ°μ§ κ°μ : μν λ³νλ₯Ό λ μ κ΅νκ² κ°μ§ν μ μλλ‘ useStateSubscriptionμ κ°μ νμ΅λλ€. μ΄μ μ½λ°± ν¨μκ° μ΅μ μνλ‘ μ μ§λλ©΄μ, μν λ³νλ₯Ό λ³΄λ€ μ ννκ² κ°μ§νκ³ λ°μν©λλ€.
νμ μ€ν¬λ¦½νΈ μ§μ κ°ν: hooks.d.ts νμΌμ ν΅ν΄ λͺ¨λ ν μ νμ μ€ν¬λ¦½νΈ μ μλ₯Ό 보μνμ΅λλ€. useStateQueryμ useStateMutationμ κ°κ° StateQueryResult λ° StateMutationResult μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ¬ λ°ν νμ μ λͺ νν μ μν©λλ€. μ΄λ¬ν νμ μ μλ κ°λ°μλ€μ΄ ν μ λ μ ννκ³ μμ νκ² μ¬μ©ν μ μλλ‘ λμ΅λλ€.
updateState ν¨μμ λΉλκΈ° μ²λ¦¬ κ°ν: updateState ν¨μλ μ΄μ μνλ₯Ό λΉλκΈ°μ μΌλ‘ μ λ°μ΄νΈν μ μλ κΈ°λ₯μ κ°μΆμμ΅λλ€. μ΄ ν¨μλ μν λ³κ²½κ³Ό ν¨κ», ν΄λΉ μνμ μ’ μλ λͺ¨λ μνλ€λ μ μ ν νμ μ λ΅ (DFS λλ BFS)μ μ¬μ©νμ¬ μ λ°μ΄νΈν©λλ€. μ΄ λ³νλ λ€μκ³Ό κ°μ μ΄μ μ μ 곡ν©λλ€:
5-1. λΉλκΈ° μν κ΄λ¦¬: updateState ν¨μλ Promiseλ₯Ό λ°ννλ―λ‘, μν μ λ°μ΄νΈ μμ μ μλ£λ₯Ό λΉλκΈ°μ μΌλ‘ κΈ°λ€λ¦΄ μ μμ΅λλ€. μ΄λ API νΈμΆκ³Ό κ°μ μΈλΆ λΉλκΈ° μμ μ ν΅ν©νλ λ° νΉν μ μ©ν©λλ€.
5-2. μ’ μ μν μ λ°μ΄νΈ: μν κ°μ μ’ μμ±μ κ³ λ €νμ¬, ν μνμ μ λ°μ΄νΈκ° μ’ μλ λ€λ₯Έ μνλ€μλ μλμΌλ‘ λ°μλ©λλ€. μ΄λ₯Ό ν΅ν΄ 볡μ‘ν μν κ°μ κ΄κ³λ₯Ό μ½κ² κ΄λ¦¬ν μ μμ΅λλ€.
5-3. DFS λ° BFS μ λ΅: μν μ λ°μ΄νΈ μ λ΅μ μν κ°μ κ΄κ³μ λ°λΌ DFS(κΉμ΄ μ°μ νμ) λλ BFS(λλΉ μ°μ νμ)λ‘ κ²°μ λ©λλ€. μ΄λ μν ꡬ쑰μ λ°λΌ μ΅μ μ μ λ°μ΄νΈ μ λ΅μ μ ννμ¬ ν¨μ¨μ μΌλ‘ μνλ₯Ό κ΄λ¦¬ν μ μκ² ν©λλ€.
μ΄λ² μ λ°μ΄νΈλ μν κ΄λ¦¬μ μμ΄ λΉλκΈ° μμ μ ν΅ν©, 볡μ‘ν μν κ΄κ³μ κ΄λ¦¬, κ·Έλ¦¬κ³ μν μ λ°μ΄νΈ μ λ΅μ μ΅μ νλ₯Ό μ§μν¨μΌλ‘μ¨, μ ν리μΌμ΄μ μ μν κ΄λ¦¬λ₯Ό λμ± κ°λ ₯νκ³ μ μ°νκ² λ§λ€ κ²μ λλ€. μ΄λ¬ν κ°μ μ νΉν μΈλΆ λ°μ΄ν° μμ€μμ μνΈμμ© λ° λ³΅μ‘ν μν μ’ μμ±μ λ€λ£° λ κ·Έ ν¨κ³Όλ₯Ό λ°νν κ²μ λλ€.
βββ How to use βββ
π¦ quickrenard π¦
: A Simple State Management in React
QuickRenard(quickrenard) is a lightweight state management solution for React applications. By providing clear paths for data querying, mutation, and subscriptions, QuickRenard streamlines the state-sharing process between components, even if they aren't directly related in the component tree.
Setup and Initialization
To start using quickrenard, you first need to define a schema for your state and then initialize the store.
1. Define State Schema:
Your state is structured based on a schema. This schema outlines the shape, type, and default values of your state properties.
// stateSchema.js
export const stateSchema = {
'childData.data': {
type: 'string',
defaultValue: 'initialValue'
}
};
2. Initialize Store:
Once you have your schema in place, initialize the state store with it. This sets up the initial state for your application.
// stateStore.js
import { initializeStore } from 'quickrenard';
import { stateSchema } from './stateSchema';
initializeStore(stateSchema);
3. Using quickrenard in Components
Querying State:
To access a state property within a component, use the useStateQuery hook. This hook queries and retrieves the value of the specified state property.
const data = useStateQuery("childData.data");
Mutating State:
For updating the state, use the useStateMutation hook. This hook provides a function to update a specific state property and also returns the current value of that property.
const [updateChildData, data] = useStateMutation("childData.data");
Subscribing to State Changes:
If you want a component to react to changes in the state, use the useStateSubscription hook. It allows you to provide a callback function that will be called whenever the specified state property changes.
useStateSubscription("childData.data", handleDataChange);
Example: Sharing State Between Distant Components
Consider a scenario where you have two components, Child and Cousin, that aren't directly related in the component tree. Yet, you want to share state data between them using QuickRenard.
Child Component:
This component mutates the data.
// Child.js
import React from 'react';
import { useStateMutation } from 'quickrenard';
function Child() {
const [updateChildData, data] = useStateMutation("childData.data");
const handleUpdateData = () => {
updateChildData("Updated Data from Child");
console.log("Data updated!");
};
return (
<div>
<h3>Child Component</h3>
<p>Data: {data}</p>
<button onClick={handleUpdateData}>Update Data</button>
</div>
);
}
Cousin Component:
This component queries the data and subscribes to its changes.
// Cousin.js
import React from 'react';
import { useStateQuery, useStateSubscription } from 'quickrenard';
function Cousin() {
const data = useStateQuery("childData.data");
const handleDataChange = () => {
console.log("Child data has changed!");
};
useStateSubscription("childData.data", handleDataChange);
return (
<div>
<h3>Cousin Component</h3>
<p>Data from Child: {data}</p>
</div>
);
}
With quickrenard, even if Child and Cousin aren't directly related, the state update in Child will trigger a subscription callback in Cousin, allowing seamless state sharing across different parts of your React application.
π¦Ver 1.2.0π¦
Added type validation logic.
- Enum validation:
- You can define an allowed set of string values through the enum key.
- It checks if the value is one of the strings defined in the enum.
- This is used when the state should only have one of specific string values.
- Object property validation:
- You can define a schema for each property of the object using the properties key.
- It verifies the type of each property to ensure it's of the correct type.
- It's used to check if each property within the object adheres to the defined schema.
- Array item type validation:
- It checks if all items in the array adhere to the specified schema.
- This is used to verify if each item inside the array follows the defined schema.
π¦Version 2.0.0π¦
Global function management feature 'functionStore' added
1. List of representative function types that can be managed:
Pure Functions: Functions that always return the same result for the same arguments without changing external state.
Utility Functions: Functions that provide reusable functionalities such as string processing, date calculations, number formatting, etc.
Helper Functions: Functions that abstract commonly used logic throughout the application (e.g., API requests).
2. While this function store can effectively manage the above types of functions, the following precautions are necessary:
Side Effects: Functions that affect or are affected by the state of external systems, (such as accessing a database or calling external APIs) can lead to unpredictable results.
State Dependency: Functions that depend on internal state may have results that are affected by changes to that state.
Scope and Closures: Functions that use variables from a specific scope need to have these dependencies managed.
Concurrency Control: Issues of concurrency that arise when multiple subscribers subscribe to the results of the same function must be managed.
π¦ Ver 2.1.0: State & Function Management in React π¦
QuickRenard is your go-to library for streamlined global state and function management within React applications. The latest update, version 2.0.0, introduces a game-changing feature: the functionStore. This new capability complements the existing state management tools, enabling developers to create, invoke, and listen to global functions throughout their component hierarchy. It simplifies the management of cross-component logic and reduces the complexity of prop drilling.
π¦ What's New in Version 2.1.0 π¦
- FunctionStore: A global registry for functions to be accessed and executed across components.
- Function Invocation: Call any registered global function from anywhere within your app.
- Function Subscriptions: Set up listeners for function calls to manage side effects or perform cleanup tasks.
- Enhanced Code Maintainability: Abstract common logic into globally accessible functions, leading to cleaner and more maintainable codebases.
π¦ Quick Start with QuickRenard's Function Store π¦
- Step 1: Import function management APIs from QuickRenard.
import { registerFunction, callFunction } from 'quickrenard';
- Step 2: Register functions that can be globally accessed.
registerFunction('logActivity', message => console.log(`Activity: ${message}`));
- Step 3: Invoke registered functions from any component, passing required arguments.
callFunction('logActivity', 'User logged in');
- Step 4: Set up subscriptions if you want components to react to function invocations.
// This part of the API is now internally managed by QuickRenard, no need for manual subscription.
- Step 5: Unsubscribe from functions to clean up listeners.
// This is also managed internally when components unmount or when you stop using the function in QuickRenard.
- QuickRenard version 2.0.0 makes your components more independent and your application more scalable by providing a central hub for state and function management.
π¦Practical Examples with QuickRenardπ¦
Example: Inter-Component Communication with State and Functions
- Let's look at how components like Child and Cousin can interact through shared state and functions without direct lineage or prop drilling.
1. Child Component:
- Here, Child updates shared state and provides a function for others to call.
// Child.js
import React from 'react';
import { useStateMutation, registerFunction } from 'quickrenard';
function Child() {
const [setChildData, childData] = useStateMutation("childData.data");
const handleUpdateData = () => {
setChildData("Updated Data from Child");
console.log("Child data updated.");
};
// Register a function for others to invoke
registerFunction('childFunction', message => {
console.log("Child received a message:", message);
return "Message processed by Child";
});
return (
<div>
<h3>Child Component</h3>
<p>Data: {childData}</p>
<button onClick={handleUpdateData}>Update Data</button>
</div>
);
}
export default Child;
2. Cousin Component:
- Cousin listens for state changes and can invoke Child's function.
// Cousin.js
import React, { useEffect } from 'react';
import { useStateQuery, useStateSubscription, callFunction } from 'quickrenard';
function Cousin() {
const childData = useStateQuery("childData.data");
useStateSubscription('childData.data', () => {
console.log("Child data has changed!");
// Invoke the function registered by Child
try {
const response = callFunction('childFunction', 'Hello World! - from Cousin');
console.log('Response from Child:', response);
} catch (error) {
console.error(error.message);
}
});
useEffect(() => {
// This will run once when the component mounts
console.log('Cousin mounted. Initial data:', childData);
}, []); // Empty dependency array to mimic componentDidMount behavior
return (
<div>
<h3>Cousin Component</h3>
<p>Data from Child: {childData}</p>
</div>
);
}
export default Cousin;
π¦Ver 2.3.0 - Ver 2.5.0π¦
Added State Caching Logic:
New Features for Performance Optimization: State caching enables swift retrieval of frequently accessed states, leading to overall performance improvements when using the library.
Previously requested state values are stored in the cache. This allows for quick responses when the same state is requested again. This feature is especially beneficial for states that require complex calculations or database queries.
It is effective in preventing network delays and server overloads. When managing remote data as state, caching can reduce the number of network requests, making data transfer more efficient.
Cautions Related to Caching:
To manage memory, the cache expires after 15 minutes(default).
From Ver 2.5.0 onwards, you can adjust the cache expiration time at your discretion. For the method and precautions, please refer to the following.
Caution: The getCacheObject function exposes the library's internal state to the outside. This function should be used for development and debugging purposes only. Modifying the cache object externally can lead to unexpected issues in the library. Instead of directly altering the cache object, please use the APIs provided by the library to change the state. While it is possible to read and monitor the contents of the cache object, altering it is not recommended.
// Example of using quickrenard
import { initializeStore, getCacheObject, subscribeStateChange } from 'quickrenard';
import { stateSchema } from './stateSchema';
// Example: Set cache expiration time to 30 minutes
initializeStore(stateSchema, { cacheExpirationTime: 1800000 });
/** π¦Optional Usage Exampleπ¦: Function for cache expiration countdown */
// Function for cache expiration countdown
function cacheExpirationCountdown() {
// Get the current time
const now = performance.now();
// Access the cache object
const cache = getCacheObject();
console.clear();
console.log("Cache Expiration Countdown:");
// Iterate through each cache key and display the remaining time
Object.keys(cache).forEach(key => {
const record = cache[key];
if (record) {
const remainingTime = record.expirationTime - now;
if (remainingTime > 0) {
console.log(`${key}: ${Math.ceil(remainingTime / 1000)} seconds remaining`);
} else {
console.log(`${key}: Expired`);
}
}
});
}
// π¦Optionally, run the countdown periodicallyπ¦
setInterval(cacheExpirationCountdown, 1000);
/** π¦Noteπ¦: This is an optional feature for monitoring cache expiration in the console.
Use it primarily for development and debugging purposes. It should be used
cautiously in a production environment as it can impact performance. */
// Example of subscribing to state changes
subscribeStateChange("someStateKey", (newState) => {
console.log("State changed:", newState);
});
Through this update, QuickRenard aims to enhance application performance and enable more efficient state management. The Ver 2.3.0 update has been focused particularly on large-scale applications and data-intensive tasks.
π¦Ver 2.6.0 - Ver 2.7.0π¦
- The state management system has become more powerful. You can now effectively manage complex dependencies between states using graph traversal algorithms. Utilize Depth-First Search (DFS) and Breadth-First Search (BFS) algorithms to effectively handle the impacts of state updates on other states.
- Depth-First Search (DFS): Explores dependencies deeply connected between states. This method is suitable when there are deep connections between states.
- Breadth-First Search (BFS): Explores dependencies across a wider range of states. This method is useful for managing influences across a broader spectrum of states.
- Enhanced State Management(βVer 2.7.0β): The state management system is now even more intelligent. It automatically determines the most effective graph traversal strategy (DFS or BFS) to manage complex dependencies between states. This enhancement simplifies the process of managing state updates and their impacts on other states.
- Key Features:
- Automated Strategy Selection: The system now automatically selects between Depth-First Search (DFS) and Breadth-First Search (BFS) based on the nature of state dependencies.
- DFS is chosen for deeply connected state dependencies (e.g., A -> B -> C).
- BFS is used when a state has multiple parallel dependencies (e.g., A -> B, C, D).
- Simplified State Updates: Users no longer need to manually choose between DFS and BFS. The system intelligently decides the optimal approach, making state management more efficient and effective.
π¦ Using setStateDependencies and updateState Functions π¦
- setStateDependencies(dependencies): Define the dependencies between different states. The system will use these dependencies to determine the traversal strategy.
const dependencies = {
'childData.data': ['parentData', 'siblingData'],
};
setStateDependencies(dependencies);
- updateState(stateKey, newValue): Update a state, and the system will automatically use DFS or BFS as needed.
const newData = "Some Data";
updateState('childData.data', newData);
console.log("State updated with the appropriate strategy");
- This approach provides a more streamlined and powerful tool for managing complex state dependencies, allowing for more tailored and efficient state updates.
π¦ Example Usage: π¦
- child.js
import React from 'react';
import { useStateMutation, updateState } from 'quickrenard';
function Child() {
const [setData, data] = useStateMutation('childData.data');
const handleUpdateData = () => {
const newData = "Updated Data from Child";
updateState('childData.data', newData);
console.log("State updated with the appropriate strategy");
// Update the state using the useStateMutation hook
setData(newData);
};
return (
<div>
<h3>Child Component</h3>
<p>Data: {data}</p>
<button onClick={handleUpdateData}>Update Data</button>
</div>
);
}
export default Child;
- stateSchema.js
export const stateSchema = {
'childData.data': {
type: 'string',
defaultValue: 'Initial Child Data',
// Define dependencies that will trigger BFS
dependencies: ['parentData', 'siblingData'] // These are parallel dependencies
},
'parentData': {
type: 'string',
defaultValue: 'Initial Parent Data'
},
'siblingData': {
type: 'string',
defaultValue: 'Initial Sibling Data'
}
};
- stateStore.js
import { initializeStore, setStateDependencies } from 'quickrenard';
import { stateSchema } from './stateSchema';
// Define state dependencies
const dependencies = {
'childData.data': ['parentData', 'siblingData'],
};
// Initialize Store
initializeStore(stateSchema);
// Set state dependencies
setStateDependencies(dependencies);
π¦ Summary π¦
- Ver 2.7.0 simplifies state management in applications with complex dependencies, automatically choosing the most efficient graph traversal strategy (DFS or BFS) based on the defined state dependencies. This enhancement streamlines state updates, reducing the need for manual intervention and improving efficiency.
π¦Ver 2.7.1 - π¦
- Independent from Lodash.
π¦Ver 2.8.1 ~ π¦
Enhancement and Expansion of State Management Hooks
Key Changes:
Improvement in useStateQuery: In Ver 2.8.0, useStateQuery has been enhanced to manage the loading and error states of data more effectively. In addition to the data field, the returned object now includes loading and error fields. These additions enable easy tracking of the data loading process and any potential errors that might occur. The inclusion of these fields allows for more detailed and nuanced handling of various scenarios that may arise during the state querying process, facilitating stronger and more flexible state management.
Expansion of useStateMutation: The logic for state change in useStateMutation has been enhanced to handle asynchronous operations. Added features manage the loading state and error handling during state changes, proving highly useful for asynchronous operations like API calls. Users can easily manage the state change function (mutate), current state (state), loading state (loading), and any errors (error) that occur.
Improved State Change Detection in useStateSubscription: The useStateSubscription has been improved for more refined detection of state changes. The callback function now maintains the latest state, accurately detecting and responding to state changes.
Enhanced TypeScript Support: The hooks.d.ts file has been updated to supplement the TypeScript definitions for all hooks. useStateQuery and useStateMutation use the StateQueryResult and StateMutationResult interfaces, respectively, to clearly define their return types. These definitions assist developers in using the hooks more accurately and safely.
Enhanced Asynchronous Processing in updateState: The updateState function now allows for asynchronous state updates. This function updates a state and all its dependent states using an appropriate traversal strategy (DFS or BFS). These changes offer the following advantages:
5-1. Asynchronous State Management: The updateState function returns a Promise, allowing asynchronous waiting for the completion of state updates. This is especially useful in integrating external asynchronous operations like API calls.
5-2. Dependent State Updates: Considering the dependencies between states, an update to one state automatically reflects in all its dependent states. This facilitates easier management of complex state relationships.
5-3. DFS and BFS Strategies: The strategy for state updates, whether DFS (Depth-First Search) or BFS (Breadth-First Search), is determined based on the relationships between states. This allows for the selection of the most efficient update strategy according to the state structure.
- This update strengthens and makes state management more flexible by integrating asynchronous operations, managing complex state relationships, and optimizing state update strategies. These improvements will be particularly effective in interactions with external data sources and handling complex state dependencies.
π¦ Example Usage (Ver 2.8.1 ~ ): π¦
- child.js
import React from 'react';
import { useStateMutation, updateState, registerFunction } from 'quickrenard';
function Child() {
// Using useStateMutation to manage 'childData.data' state.
// This hook returns the current state value.
const { state: data } = useStateMutation('childData.data');
const handleUpdateData = () => {
const newData = "Updated Data from Child";
// Calling the asynchronous updateState function to update 'childData.data'.
// It returns a Promise, allowing us to handle the completion or failure of the update.
updateState('childData.data', newData)
.then(() => {
// Logging on successful state update.
console.log("State and dependent states updated with the appropriate strategy");
})
.catch(err => {
// Logging in case of an error.
console.error("Error updating state:", err);
});
};
// Registering a function 'childFunction' that can be called by the Cousin component.
// This function logs a message received from the Cousin component.
registerFunction('childFunction', (message) => {
console.log("Message from Cousin:", message);
return "Response from Child";
});
return (
<div>
<h3>Child Component</h3>
<p>Data: {data}</p>
<button onClick={handleUpdateData}>Update Data</button>
</div>
);
}
export default Child;
- cousin.js
import React, { useEffect, useState } from 'react';
import { useStateQuery, useStateSubscription } from 'quickrenard';
function Cousin() {
// Use useStateQuery to manage the state of 'childData.data'.
// This hook returns an object with { data, loading, error } for 'childData.data'.
const { data: childData, loading: childLoading, error: childError } = useStateQuery('childData.data');
// Use useStateQuery to manage the state of 'parentData'.
// The hook fetches the current state of 'parentData'.
const { data: parentData } = useStateQuery('parentData');
// Use useStateQuery to manage the state of 'siblingData'.
// The hook fetches the current state of 'siblingData'.
const { data: siblingData } = useStateQuery('siblingData');
// Local states to display data, initialized with the data from useStateQuery.
const [displayedChildData, setDisplayedChildData] = useState(childData);
const [displayedParentData, setDisplayedParentData] = useState(parentData);
const [displayedSiblingData, setDisplayedSiblingData] = useState(siblingData);
// Subscribe to changes in 'childData.data' and update displayedChildData accordingly.
// This will re-render the component with new child data when it changes.
useStateSubscription('childData.data', (newData) => {
console.log("Child data has changed!");
setDisplayedChildData(newData);
});
// Subscribe to changes in 'parentData' and update displayedParentData accordingly.
// This will re-render the component with new parent data when it changes.
useStateSubscription('parentData', (newData) => {
console.log("Parent data has changed!");
setDisplayedParentData(newData);
});
// Subscribe to changes in 'siblingData' and update displayedSiblingData accordingly.
// This will re-render the component with new sibling data when it changes.
useStateSubscription('siblingData', (newData) => {
console.log("Sibling data has changed!");
setDisplayedSiblingData(newData);
});
// useEffect to log when Cousin component mounts.
// Useful for checking if the component is correctly mounted.
useEffect(() => {
console.log('Cousin mounted.');
}, []);
// Render the loading state, error state, or the actual data from childData, parentData, and siblingData.
return (
<div>
<h3>Cousin Component</h3>
<p>Child Data: {childLoading ? 'Loading...' : childError ? childError.message : displayedChildData}</p>
<p>Parent Data: {displayedParentData}</p>
<p>Sibling Data: {displayedSiblingData}</p>
</div>
);
}
export default Cousin;
- stateSchema.js
export const stateSchema = {
'childData.data': {
type: 'string',
defaultValue: 'Initial Child Data',
dependencies: ['parentData', 'siblingData']
},
'parentData': {
type: 'string',
defaultValue: 'Initial Parent Data'
},
'siblingData': {
type: 'string',
defaultValue: 'Initial Sibling Data'
}
};
- stateStore.js
// stateStore.js
import { initializeStore, getCacheObject, setStateDependencies } from 'quickrenard';
import { stateSchema } from './stateSchema';
// Define state dependencies
const dependencies = {
'childData.data': ['parentData', 'siblingData'],
};
// Initialize Store
// Example: Set cache expiration time to 30 minutes
initializeStore(stateSchema, { cacheExpirationTime: 1800000 });
// // Set state dependencies
setStateDependencies(dependencies);
/** π¦Optional Usage Exampleπ¦: Function for cache expiration countdown */
// Function for cache expiration countdown
function cacheExpirationCountdown() {
// Get the current time
const now = performance.now();
// Access the cache object
const cache = getCacheObject();
console.clear();
console.log("Cache Expiration Countdown:");
// Iterate through each cache key and display the remaining time
Object.keys(cache).forEach(key => {
const record = cache[key];
if (record) {
const remainingTime = record.expirationTime - now;
if (remainingTime > 0) {
console.log(`${key}: ${Math.ceil(remainingTime / 1000)} seconds remaining`);
} else {
console.log(`${key}: Expired`);
}
}
});
}
// π¦Optionally, run the countdown periodicallyπ¦
setInterval(cacheExpirationCountdown, 1000);
Adjust your component implementations as necessary to align with these examples and the unique details of your project. This documentation is designed to provide a conceptual understanding of QuickRenard's enhanced functionality.
π¦Licenseπ¦
- This project is licensed under the MIT License - see the LICENSE.md file for details.
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago