OBS (Open Broadcaster Software) is a free and open-source software for video recording and live streaming. To begin:
- Visit the OBS official website.
- Download the installer for your operating system (Windows, macOS, or Linux).
- Follow the installation instructions to set up OBS on your system.
Once OBS is installed, you need to add a video source to start recording:
- Open OBS and navigate to the "Sources" panel.
- Click the "+" button to add a new source.
- Select the type of source you want to add (e.g., Display Capture, Window Capture, Video Capture Device).
- Configure the source settings as needed and click "OK".
To ensure your recordings are saved in the desired location and format:
- Go to the "Settings" menu in OBS.
- Navigate to the "Output" tab.
- Under the "Recording" section, set the recording path to the folder where you want to save your recordings.
- Choose the recording format (e.g., mp4, flv) based on your requirements.
The Aero system configuration tool, provided by the juxt/aero
library, is a configuration library for Clojure
applications. It leverages EDN (Extensible Data Notation) for defining configuration files and provides features to
handle various configuration needs like environment-specific settings, type coercion, and more.
EDN (Extensible Data Notation) is a subset of Clojure used for data interchange. It is often used in configuration files for Clojure applications. To use EDN files in your project:
- Create a
.edn
file for your configuration data. - Use the EDN format to structure your data in a human-readable way.
Multi profiles allow you to manage different configuration settings for various environments (e.g., development, testing, production):
- Define multiple profiles in your EDN configuration file.
- Use a profile key to switch between different sets of configurations.
ENV keys are used to reference environment variables in your configuration:
- Use the
#:env
prefix in your EDN file to denote environment variables. - Ensure your environment variables are set correctly in your system or deployment environment.
Type coercion ensures that configuration values are automatically converted to the appropriate data types:
- Define the expected types in your EDN file.
- Use a library like Aero to handle the type coercion based on the defined schema.
Explanation:
The Aero system configuration tool, provided by the juxt/aero
library, is a configuration library for Clojure applications. It leverages EDN (Extensible Data Notation) for defining configuration files and provides features to handle various configuration needs like environment-specific settings, type coercion, and more.
-
EDN Files:
- What: Uses EDN format for configuration files, which is a subset of Clojure's syntax designed for data interchange.
- Why: EDN files are human-readable, easy to write, and support rich data structures.
-
Multi Profiles:
- What: Supports defining multiple profiles within a single configuration file.
- Why: Allows you to manage different configurations for different environments (e.g., development, testing, production) within the same file.
-
ENV Keys:
- What: Allows referencing environment variables directly within the configuration file.
- Why: Enables dynamic configuration based on the environment in which the application is running, enhancing flexibility and security.
-
Type Coercion:
- What: Automatically converts configuration values to the appropriate data types based on the schema defined in the configuration.
- Why: Ensures that configuration values are interpreted correctly as the intended data types, reducing the risk of errors.
Here is a simple example to illustrate how Aero can be used:
-
EDN Configuration File (
config.edn
):{ ;; Define profiles :profiles { :dev {:db-url "jdbc:postgresql://localhost/dev-db"} :prod {:db-url "jdbc:postgresql://prod-db-server/prod-db"} } ;; Reference environment variables :api-key #:env "API_KEY" ;; Use type coercion for port number :server-port ^:int 8080 }
-
Clojure Code to Read Configuration:
(ns my-app.config (:require [aero.core :refer (read-config)])) (def config (read-config "config.edn")) ;; Access configuration values (def db-url (:db-url config)) (def api-key (:api-key config)) (def server-port (:server-port config))
In this example:
- Multiple profiles (
:dev
and:prod
) are defined, allowing the application to switch between different database URLs based on the environment. - The
:api-key
is retrieved from an environment variable, making the configuration flexible and secure. - The
:server-port
is coerced to an integer type, ensuring the value is correctly interpreted.
Aero simplifies managing configuration in Clojure applications, making it easier to maintain and adapt to different environments and requirements.
There are two different ways to create and connect a project to GitHub:
- Create a project from scratch using the terminal.
- Connect an already existing project to GitHub.
To create a new repository and push it to GitHub from the command line, follow these steps:
-
Create a
README.md
file:echo "# artchess" >> README.md
Explanation: This command creates a new file named
README.md
and adds a line with the text# artchess
to it. TheREADME.md
file is typically used to provide information about your project. -
Initialize a New Git Repository:
git init
Explanation: This command initializes a new Git repository in your current directory. It creates a
.git
directory that contains all the necessary files and structures for version control. -
Add
README.md
to the Repository:git add README.md
Explanation: This command stages the
README.md
file, marking it for inclusion in the next commit. -
Commit the Staged Files:
git commit -m "first commit"
Explanation: This command commits the staged files with the message "first commit". Commits are snapshots of your repository at specific points in time.
-
Create and Switch to the Main Branch:
git branch -M main
Explanation: This command creates a new branch named
main
and switches to it. The-M
flag renames the current branch tomain
. -
Add Remote Repository:
git remote add origin [email protected]:VictorInacio/artchess.git
Explanation: This command adds a remote repository named
origin
. The remote repository is hosted on GitHub, and the URL specifies where the repository is located. -
Push to the Remote Repository:
git push -u origin main
Explanation: This command pushes your local commits to the
main
branch of the remote repository. The-u
flag sets the remoteorigin
as the default upstream for themain
branch.
To connect an existing project to a remote repository, follow these steps:
-
Initialize a New Git Repository (if not already initialized):
git init
Explanation: This command initializes a new Git repository in your current directory if it has not already been initialized.
-
Stage All Files:
git add .
Explanation: This command stages all files in the current directory for inclusion in the next commit.
-
Commit the Staged Files:
git commit -m "Initial commit"
Explanation: This command commits the staged files with the message "Initial commit".
-
Create and Switch to the Main Branch:
git branch -M main
Explanation: This command creates a new branch named
main
and switches to it. The-M
flag renames the current branch tomain
. -
Add Remote Repository:
git remote add origin [email protected]:VictorInacio/artchess.git
Explanation: This command adds a remote repository named
origin
. The remote repository is hosted on GitHub, and the URL specifies where the repository is located. -
Push to the Remote Repository:
git push -u origin main
Explanation: This command pushes your local commits to the
main
branch of the remote repository. The-u
flag sets the remoteorigin
as the default upstream for themain
branch.
In a Clojure project, dependencies are managed using the deps.edn
file, which is a data-oriented way of specifying dependencies, unlike Maven's XML format. Here's how to interpret the Maven dependency for org.clojure/java.jdbc
:
{:deps
{org.clojure/java.jdbc {:mvn/version "0.7.12"}}
}
-
:deps
: This key indeps.edn
specifies the dependencies map where you define all the libraries your project depends on. -
org.clojure/java.jdbc
: This is the coordinate identifier for the dependency. It consists of:- Group ID (
org.clojure
): Indicates the group or organization that maintains the library. In this case, it's Clojure itself (org.clojure
). - Artifact ID (
java.jdbc
): Identifies the specific library or artifact within the group. Here,java.jdbc
refers to the Clojure library for JDBC (Java Database Connectivity).
- Group ID (
-
:mvn/version "0.7.12"
: This specifies the version of the library you want to use. It follows the Maven versioning syntax, where"0.7.12"
is the version number of thejava.jdbc
library.
- Group ID: Identifies the organization or group responsible for the library.
- Artifact ID: Specifies the specific library or module within the group.
- Version: Specifies the version of the library to use. It follows semantic versioning principles (
major.minor.patch
).
- Consistency: Maven provides a standardized way to manage dependencies across projects.
- Automation: Tools like
clj
orlein
automate the fetching and management of dependencies based ondeps.edn
specifications. - Compatibility: Ensures that compatible versions of libraries are used, reducing compatibility issues.
The Maven dependency declaration org.clojure/java.jdbc {:mvn/version "0.7.12"}
in your deps.edn
file specifies that
your Clojure project requires version 0.7.12
of the java.jdbc
library from the org.clojure
group. Maven coordinates
(group ID
, artifact ID
, version
) are crucial for specifying and managing dependencies effectively in Clojure projects.
com.github.seancorfield/honeysql
is a library in Clojure that facilitates building SQL queries programmatically using Clojure data structures instead of strings. This approach enhances code readability, maintainability, and safety against SQL injection attacks.
Add honeysql
to your deps.edn
file:
{:deps
{com.github.seancorfield/honeysql {:mvn/version "0.6.2"}}
}
Let's explore how to use honeysql
for common database operations.
(ns your-app.db
(:require [honeysql.core :as sql]
[honeysql.helpers :refer [select]]))
;; Construct a select query
(def select-query
(-> (select :*)
(sql/from :users)
(sql/where [:= :status "active"])
sql/format))
(println "Generated SQL query:" select-query)
- Explanation:
select :*
constructs aSELECT *
statement.sql/from :users
specifies the tableusers
.sql/where [:= :status "active"]
adds aWHERE status = 'active'
condition.sql/format
converts the query data structure into a SQL string.
(ns your-app.db
(:require [honeysql.core :as sql]
[honeysql.helpers :refer [insert]]))
;; Construct an insert query
(def insert-query
(-> (insert-into :users)
(sql/values {:name "Alice" :age 30}))
sql/format))
(println "Generated SQL query:" insert-query)
- Explanation:
insert-into :users
specifies theINSERT INTO users
statement.sql/values {:name "Alice" :age 30}
specifies the values to insert into the table.sql/format
converts the query data structure into a SQL string.
(ns your-app.db
(:require [honeysql.core :as sql]
[honeysql.helpers :refer [update]]))
;; Construct an update query
(def update-query
(-> (update :users)
(sql/set-fields {:age 31})
(sql/where [:= :name "Alice"]))
sql/format))
(println "Generated SQL query:" update-query)
- Explanation:
update :users
constructs theUPDATE users
statement.sql/set-fields {:age 31}
specifies the fields to update (age
set to31
).sql/where [:= :name "Alice"]
adds aWHERE name = 'Alice'
condition.sql/format
converts the query data structure into a SQL string.
-
src
Directory:src
: The main source code directory where the application's code is stored.
-
resources
Directory:resources
: A directory for storing non-code resources such as configuration files, static files, and other assets.
In many projects, you might see paths defined like this:
src
: Contains all the source code files.resources
: Contains all the resource files needed by the application.
Example structure:
my-project/
├── src/
│ └── main/
│ ├── app/
│ │ └── main.py
│ └── utils/
│ └── helper.py
└── resources/
└── config/
└── settings.yaml
This structure helps in maintaining a clean separation between code and resources, making the project easier to navigate and manage.
-
Create
public
Directory inresources
:- Step: Create a
public
directory inside theresources
directory. - Purpose: To store frontend-related files, such as HTML, CSS, and JavaScript.
- Step: Create a
-
Create
index.html
:- Step: Inside the
public
directory, create anindex.html
file. - Important Detail: Ensure that the
<script src="js/main.js"></script>
tag correctly points to themain.js
file path. The main.js file will be generated by shadow-cljs during the build process. This is configured in the shadow-cljs settings with the :output-dir option, which specifies that the compiled JavaScript files will be placed in the resources/public/js directory. - Purpose: This file serves as the entry point for the frontend application.
- Step: Inside the
-
Create and Set Up Shadow-cljs.edn File and Settings:
- Step: In the root directory of your project, create a
shadow-cljs.edn
file. - Purpose: To configure the shadow-cljs build tool for your project.
- Detail:
- Build Configuration: Define a build configuration for your app. This includes specifying the target platform, entry points, and output directory.
- Output Directory: Ensure that the
:output-dir
option in the build configuration matches the path specified in the<script>
tag of yourindex.html
file. - Entry Point: The
:entries
option in the:modules
section specifies the namespace that serves as the entry point for the application. This should match the namespace where your main initialization function is defined. - Initialization Function: The
:init-fn
option specifies the function to call to initialize the application. This should be a fully qualified symbol pointing to your initialization function.
- Step: In the root directory of your project, create a
-
Create
app
Directory insrc
:- Step: Inside the
src
directory, create anapp
directory to hold frontend code. - File: Create a
core.cljs
file and add the app component as the initial page. - Purpose: To keep frontend code organized and separate from backend code.
- Step: Inside the
-
Create
shadow-cljs.edn
File:- Step: In the root directory of your project, create a
shadow-cljs.edn
file. - Purpose: To configure the shadow-cljs build tool for your project.
- Step: In the root directory of your project, create a
- Purpose: Indicates that the project is using a dependencies management system, typically
deps.edn
. - Usage:
{ :deps true }
enablesshadow-cljs
to use dependencies fromdeps.edn
.
- Purpose: Configures the Network REPL (nREPL) for Clojure development.
- Options:
:port
: Specifies the port number on which the nREPL server listens.
- Example:
:nrepl {:port 9000}
- Purpose: Defines the build configurations for different targets in the project.
- Usage: Each build configuration is specified under a unique key (e.g.,
:app
).
-
:target
- Purpose: Specifies the target environment for the build.
- Common Values:
:browser
: For browser-based applications.:node-script
: For Node.js scripts.
- Example:
:target :browser
-
:modules
- Purpose: Defines the JavaScript modules to be generated by the build.
- Options:
:main
: Specifies the entry point module.:entries
: A list of namespaces to include in the module.:init-fn
: The initialization function to be called when the module is loaded.
- Example:
:modules {:main {:entries [app.core] :init-fn app.core/init}}
-
:output-dir
- Purpose: Specifies the directory where the compiled JavaScript files will be output.
- Example:
:output-dir "resources/public/js"
-
:devtools
- Purpose: Configures development tools and preloads.
- Options:
:preloads
: A list of namespaces to preload during development.
- Example:
:devtools {:preloads [devtools.preload day8.re-frame-10x.preload]}
-
:compiler-options
- Purpose: Customizes the ClojureScript compiler options.
- Options:
:closure-defines
: Defines constants for the Google Closure compiler.- Example:
:compiler-options {:closure-defines {goog.DEBUG true re-frame.trace.trace-enabled? true day8.re-frame.tracing.trace-enabled? true}}
-
:dev
- Purpose: Contains configurations specific to the development environment.
- Options:
:compiler-options
: Additional compiler options for development mode.
- Example:
:dev {:compiler-options {:closure-defines {re-frame.trace.trace-enabled? true day8.re-frame.tracing.trace-enabled? true}}}
-
:release
- Purpose: Contains configurations specific to the release (production) environment.
- Options:
:build-options
: Additional build options for release mode.
- Example:
:release {:build-options {:ns-aliases {day8.re-frame.tracing day8.re-frame.tracing-stubs}}}
{
:deps true ;; Enables using dependencies from deps.edn
:nrepl {:port 9000} ;; Configures nREPL to listen on port 9000
:builds {:app {
:target :browser ;; Specifies that the target environment is the browser
:modules {:main {:entries [app.core]
:init-fn app.core/init}} ;; Specifies the entry point module and init function
:output-dir "resources/public/js" ;; Directory where compiled JS files are output
:devtools {:preloads [devtools.preload day8.re-frame-10x.preload]} ;; Preloads namespaces for development tools
:compiler-options {:closure-defines {goog.DEBUG true
re-frame.trace.trace-enabled? true
day8.re-frame.tracing.trace-enabled? true}} ;; Defines constants for the Closure compiler
:dev {:compiler-options {:closure-defines {re-frame.trace.trace-enabled? true
day8.re-frame.tracing.trace-enabled? true}}} ;; Development-specific compiler options
:release {:build-options {:ns-aliases {day8.re-frame.tracing day8.re-frame.tracing-stubs}}} ;; Release-specific build options
}
}
}
:output-dir
must match the directory specified in yourindex.html
file’s<script src="js/main.js"></script>
tag. This ensures the generatedmain.js
file is correctly linked.:init-fn
must point to the correct initialization function in your ClojureScript code. This function is responsible for rendering your frontend application.
-
Add Dependencies in
deps.edn
:- Step: Update the
deps.edn
file with necessary dependencies. - Purpose: To manage project dependencies for both backend and frontend.
- Step: Update the
-
Create
package.json
and Add Dependencies:- Step: In the root directory of your project, create a
package.json
file. - Content: Add the necessary dependencies and scripts.
- Purpose: To manage JavaScript dependencies and scripts for building the frontend.
- Step: In the root directory of your project, create a
-
Install Dependencies:
- Step: Run
yarn install
to install the dependencies listed inpackage.json
. - Purpose: To ensure all JavaScript dependencies are installed.
- Step: Run
my-project/
├── src/
│ └── main/
│ └── app/
│ └── core.cljs
├── resources/
│ └── public/
│ └── index.html
│ └── js/
│ └── main.js
├── shadow-cljs.edn
├── deps.edn
├── package.json
└── yarn.lock
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.11.1"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
org.clojure/tools.namespace {:mvn/version "1.4.4"}
;; DB
org.postgresql/postgresql {:mvn/version "42.2.2"}
org.clojure/java.jdbc {:mvn/version "0.7.12"}
com.github.seancorfield/honeysql {:mvn/version "2.4.1045"}
;; HTTP Server
io.pedestal/pedestal.service {:mvn/version "0.6.2"}
io.pedestal/pedestal.route {:mvn/version "0.6.2"}
io.pedestal/pedestal.jetty {:mvn/version "0.6.2"}
org.clojure/data.json {:mvn/version "2.4.0"}
;; Utils
aero/aero {:mvn/version "1.1.6"}
;; FRONTEND
com.adamrenklint/preo {:mvn/version "0.1.0"}
com.pitch/uix.core {:mvn/version "1.0.1"}
com.pitch/uix.dom {:mvn/version "1.0.1"}
re-frame/re-frame {:mvn/version "1.3.0"}
cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}
day8.re-frame/tracing {:mvn/version "0.6.2"}
cljs-http/cljs-http {:mvn/version "0.1.48"
:exclusions [io.grpc/grpc-netty-shaded]}
reagent-utils/reagent-utils {:mvn/version "0.3.8"}}
:aliases {:dev {:extra-paths ["dev"]
:extra-deps {thheller/shadow-cljs {:mvn/version "2.25.8"}
binaryage/devtools {:mvn/version "1.0.7"}
day8.re-frame/tracing {:mvn/version "0.6.2"}
day8.re-frame/re-frame-10x {:mvn/version "1.6.0"}}}}}
{:deps true
:nrepl {:port 9000}
:builds {:app {:target :browser
:modules {:main {:entries [app.core]
:init-fn app.core/init}}
:devtools {:preloads [devtools.preload day8.re-frame-10x.preload]}
-----> :output-dir "resources/public/js" <------ to create public.jc.main.js
:compiler-options {:closure-defines {goog.DEBUG true
re-frame.trace.trace-enabled? true
day8.re-frame.tracing.trace-enabled? true
"re_frame.trace.trace_enabled_QMARK_" true
"day8.re_frame.tracing.trace_enabled_QMARK_" true}}
:dev {:compiler-options {:closure-defines {re-frame.trace.trace-enabled? true
day8.re-frame.tracing.trace-enabled? true}}}
:release {:build-options {:ns-aliases {day8.re-frame.tracing day8.re-frame.tracing-stubs}}}}}}
{
"name": "ArtChessAcademy",
"scripts": {
"dev": "shadow-cljs -A:dev watch app",
"release": "shadow-cljs -A:dev release app"
},
"dependencies": {
"highlight.js": "11.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-refresh": "^0.14.0",
"shadow-cljs": "2.22.9"
}
}
(ns app.core
(:require
[uix.core :as uix :refer [defui $]]
[uix.dom]
["react" :as react]))
(enable-console-print!)
(defui app []
(let [[n set-n] (uix/use-state 0)]
($ :.flex.flex-col.justify-center.items-center.h-screen
($ :img.animate-bounce
{:src "https://raw.githubusercontent.com/pitch-io/uix/master/logo.png"
:width 128})
($ :div.text-xl.mb-4 "Hello")
($ :div.text-4xl.animate-ping "👋"))))
(defn render []
(uix.dom/render-root ($ react/StrictMode ($ app))
(uix.dom/create-root
(js/document.getElementById "root"))))
(defn ^:export init []
(render))
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Art Chess Academy</title>
</head>
<body>
<div id="root"></div>
<script src="js/main.js"></script> <------ this file going to create by shadow-cljs by this option: :output-dir "resources/public/js"
</body>
</html>
Re-frame is a ClojureScript framework for building web applications using a reactive and functional approach. It follows a unidirectional data flow pattern, which simplifies the management of state and side effects.
-
Events: Represent user interactions or other actions that modify the application's state. Events are dispatched and handled by event handlers.
-
Subscriptions: Provide a way to read data from the application's state and pass it to components. Subscriptions automatically re-calculate and trigger re-renders when the state they depend on changes.
-
Dispatch: The mechanism used to send events into the application’s event handling system. Dispatching an event triggers a chain of actions that ultimately leads to a state update.
Events are defined using rf/reg-event-db
(for database changes) or rf/reg-event-fx
(for side effects). An event handler takes the current state and event arguments, processes them, and returns a new state.
Example: Define an Event Handler to Increment a Counter
(rf/reg-event-db
:increment-counter
(fn [db _]
;; Increment the counter in the application state
(update db :counter inc)))
:increment-counter
is the event name.db
is the current application state.update db :counter inc
increments the value of the:counter
key in the state.
Dispatching an event sends it to the event handling system, which then invokes the appropriate event handler.
Example: Dispatch an Event on Button Click
(defn increment-button []
($ :button {:onClick #(rf/dispatch [:increment-counter])} "Increment"))
rf/dispatch
sends the:increment-counter
event to the event handling system.- When the button is clicked, the
:increment-counter
event is dispatched.
The event handler processes the event and updates the application state. The updated state is then used to re-render the UI.
Example Event Handler
(rf/reg-event-db
:increment-counter
(fn [db _]
(update db :counter inc)))
- This handler updates the
:counter
key in the state by incrementing its value.
The event handler updates the application's state, which is managed by Re-frame’s database. The state update triggers recalculation of subscriptions that depend on the changed state.
Example Initial State
(def initial-state
{:counter 0})
Subscriptions are used to read specific parts of the application state and provide them to components. When the state changes, subscriptions are recalculated.
Example Subscription
(rf/reg-sub
:counter
(fn [db _]
(:counter db)))
:counter
is the subscription name.- The subscription function extracts the
:counter
value from the state.
Components use subscriptions to get the data they need to render. When a subscription’s underlying state changes, the component re-renders with the new data.
Example Component Using Subscription
(defui counter-component []
(let [counter (hooks/use-subscribe [:counter])]
($ :div
($ :h3 "Counter: " counter))))
hooks/use-subscribe
is used to get the current value of the:counter
subscription.- The component re-renders whenever the
:counter
value changes.
Here's a complete example showing the entire flow:
-
Event Registration
(rf/reg-event-db :increment-counter (fn [db _] (update db :counter inc)))
-
Subscription Registration
(rf/reg-sub :counter (fn [db _] (:counter db)))
-
Component Using Subscription
(defui counter-component [] (let [counter (hooks/use-subscribe [:counter])] ($ :div ($ :h3 "Counter: " counter))))
-
Dispatch Event on User Interaction
(defn increment-button [] ($ :button {:onClick #(rf/dispatch [:increment-counter])} "Increment"))
Here’s a simplified flow of the dispatch event process:
-
User Interaction
(e.g., button click triggersonClick
) -
Event Dispatch
(rf/dispatch [:increment-counter]
) -
Event Handling
(:increment-counter
event is processed by its handler) -
State Update
(Application state is updated) -
Subscription Recalculation
(Subscriptions that depend on the updated state are recalculated) -
Component Re-rendering
(UI components are re-rendered with new state data)
- Events represent actions and are dispatched to modify state.
- Subscriptions extract and provide state data to components.
- Dispatch triggers the entire process, leading to state updates and UI changes.
The app.hooks
namespace provides custom hooks that integrate Reagent's reaction system with React’s hooks API. This namespace is crucial for managing and synchronizing state between Re-frame subscriptions and Reagent components in a way that aligns with React's component lifecycle.
-
use-batched-subscribe
:- Manages listeners for changes to an atom-like reference (
ref
). It ensures that all registered listeners are notified when the reference changes and handles cleanup when listeners are removed.
- Manages listeners for changes to an atom-like reference (
-
use-sync-external-store
:- Facilitates subscription to an external store using React’s
useSyncExternalStore
hook. This ensures that components can stay in sync with external state sources by getting the current snapshot and updating when changes occur.
- Facilitates subscription to an external store using React’s
-
run-reaction
:- Manages Reagent reactions by scheduling updates and notifying listeners in batches. This function is used to ensure that changes in Reagent's reaction system are properly handled and applied.
-
use-reaction
:- Integrates Reagent reactions with React’s hooks system. It subscribes components to changes in Reagent reactions and returns the current value of the reaction. This allows React components to respond to state changes managed by Reagent.
-
use-subscribe
:- Provides a hook for subscribing to Re-frame subscriptions. It creates and manages a subscription to a Re-frame query, ensuring that React components stay updated with the latest state from Re-frame.
The app.hooks
namespace is essential for bridging the gap between Reagent and React. It enables seamless state management and synchronization between Reagent’s reaction system and React’s hooks, allowing for efficient and reactive UI updates.
foo