Hooks
Overview¶
Prefabricated hooks can be used within your components.py
to help simplify development.
Note
Looking for standard React hooks?
This package only contains Django specific hooks. Standard hooks can be found within reactive-python/reactpy
.
Database Hooks¶
Use Query¶
Execute functions in the background and return the result, typically to read data from the Django ORM.
The default postprocessor expects your query function to return
a Django Model
or QuerySet
. This needs to be changed or disabled to execute other types of queries.
Query functions can be sync or async.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
1 2 3 4 5 |
|
See Interface
Parameters
Name | Type | Description | Default |
---|---|---|---|
options | QueryOptions | None | An optional QueryOptions object that can modify how the query is executed. | None |
query | Callable[_Params, _Result | None] | A callable that returns a Django Model or QuerySet . | N/A |
*args | _Params.args | Positional arguments to pass into query . | N/A |
**kwargs | _Params.kwargs | Keyword arguments to pass into query . | N/A |
Returns
Type | Description |
---|---|
Query[_Result | None] | An object containing loading /error states, your data (if the query has successfully executed), and a refetch callable that can be used to re-run the query. |
How can I provide arguments to my query function?
*args
and **kwargs
can be provided to your query function via use_query
parameters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
How can I customize this hook's behavior?
This hook accepts a options: QueryOptions
parameter that can be used to customize behavior.
Below are the settings that can be modified via these QueryOptions
.
thread_sensitive
Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async
docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
postprocessor
By default, automatic recursive fetching of ManyToMany
or ForeignKey
fields is enabled within the django_query_postprocessor
. This is needed to prevent SynchronousOnlyOperation
exceptions when accessing these fields within your ReactPy components.
However, if you...
- Want to use this hook to defer IO intensive tasks to be computed in the background
- Want to to utilize
use_query
with a different ORM
... then you can either set a custom postprocessor
, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor
parameter. In the example below, we will set the postprocessor
to None
to disable postprocessing behavior.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
If you wish to create a custom postprocessor
, you will need to create a callable.
The first argument of postprocessor
must be the query data
. All proceeding arguments are optional postprocessor_kwargs
(see below). This postprocessor
must return the modified data
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
postprocessor_kwargs
By default, automatic recursive fetching of ManyToMany
or ForeignKey
fields is enabled within the django_query_postprocessor
. This is needed to prevent SynchronousOnlyOperation
exceptions when accessing these fields within your ReactPy components.
However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query
hook.
You can disable the prefetching behavior of the default postprocessor
(located at reactpy_django.utils.django_query_postprocessor
) via the QueryOptions.postprocessor_kwargs
parameter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set
by default.
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation
exception.
These SynchronousOnlyOperation
exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.
Can I make a failed query try again?
Yes, a use_mutation
can be re-performed by calling reset()
on your use_mutation
instance.
For example, take a look at reset_event
below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
1 2 3 4 5 |
|
Why does the example query function return TodoItem.objects.all()
?
This design decision was based on Apollo's useQuery
hook, but ultimately helps avoid Django's SynchronousOnlyOperation
exceptions.
With the Model
or QuerySet
your function returns, this hook uses the default postprocessor to ensure that all deferred or lazy fields are executed.
Use Mutation¶
Modify data in the background, typically to create/update/delete data from the Django ORM.
Mutation functions can return False
to manually prevent your refetch=...
function from executing. All other returns are ignored.
Mutation functions can be sync or async.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
1 2 3 4 5 |
|
See Interface
Parameters
Name | Type | Description | Default |
---|---|---|---|
mutation | Callable[_Params, bool | None] | A callable that performs Django ORM create, update, or delete functionality. If this function returns False , then your refetch function will not be used. | N/A |
refetch | Callable[..., Any] | Sequence[Callable[..., Any]] | None | A query function (the function you provide to your use_query hook) or a sequence of query functions that need a refetch if the mutation succeeds. This is useful for refreshing data after a mutation has been performed. | None |
Returns
Type | Description |
---|---|
Mutation[_Params] | An object containing loading /error states, a reset callable that will set loading /error states to defaults, and a execute callable that will run the query. |
How can I provide arguments to my mutation function?
*args
and **kwargs
can be provided to your mutation function via mutation(...)
parameters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
How can I customize this hook's behavior?
This hook accepts a options: MutationOptions
parameter that can be used to customize behavior.
Below are the settings that can be modified via these MutationOptions
.
thread_sensitive
Whether to run your synchronous mutation function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async
docs docs for more information.
This setting only applies to sync query functions, and will be ignored for async functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Can I make ORM calls without hooks?
Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation
exception.
These SynchronousOnlyOperation
exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.
Can I make a failed mutation try again?
Yes, a use_mutation
can be re-performed by calling reset()
on your use_mutation
instance.
For example, take a look at reset_event
below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
1 2 3 4 5 |
|
Can use_mutation
trigger a refetch of use_query
?
Yes, use_mutation
can queue a refetch of a use_query
via the refetch=...
argument.
The example below is a merge of the use_query
and use_mutation
examples above with the addition of a use_mutation(refetch=...)
argument.
Please note that refetch
will cause all use_query
hooks that use get_items
in the current component tree will be refetched.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
1 2 3 4 5 |
|
Use User Data¶
Store or retrieve data (dict
) specific to the connection's User
. This data is stored in the REACTPY_DATABASE
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
See Interface
Parameters
Name | Type | Description | Default |
---|---|---|---|
default_data | None | dict[str, Callable[[], Any] | Callable[[], Awaitable[Any]] | Any] | A dictionary containing {key: default_value} pairs. For computationally intensive defaults, your default_value can be sync or async functions that return the value to set. | None |
save_default_data | bool | If True , default_data values will automatically be stored within the database if they do not exist. | False |
Returns
Type | Description |
---|---|
UserData | A NamedTuple containing a Query and Mutation objects used to access/modify user data. Read the use_query and use_mutation docs for more details. |
How do I set default values?
You can configure default user data via the default_data
parameter.
This parameter accepts a dictionary containing a {key: default_value}
pairs. For computationally intensive defaults, your default_value
can be sync or async functions that return the value to set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Connection Hooks¶
Use Connection¶
Returns the active connection, which is either a Django WebSocket or a HTTP Request.
1 2 3 4 5 6 7 8 9 |
|
See Interface
Parameters
None
Returns
Type | Description |
---|---|
Connection | An object that contains a carrier (WebSocket or HttpRequest ), scope , and location . |
Use Scope¶
Shortcut that returns the WebSocket or HTTP connection's scope.
1 2 3 4 5 6 7 8 9 |
|
See Interface
Parameters
None
Returns
Type | Description |
---|---|
MutableMapping[str, Any] | The connection's scope . |
Use Location¶
Shortcut that returns the browser's current Location
.
1 2 3 4 5 6 7 8 9 |
|
See Interface
Parameters
None
Returns
Type | Description |
---|---|
Location | An object containing the current URL's pathname and search query. |
Use Origin¶
Shortcut that returns the WebSocket or HTTP connection's origin
.
You can expect this hook to provide strings such as http://example.com
.
1 2 3 4 5 6 7 8 9 |
|
See Interface
Parameters
None
Returns
Type | Description |
---|---|
str | None | A string containing the browser's current origin, obtained from WebSocket or HTTP headers (if available). |
Use User¶
Shortcut that returns the WebSocket or HTTP connection's User
.
1 2 3 4 5 6 7 8 9 |
|
See Interface
Parameters
None
Returns
Type | Description |
---|---|
AbstractUser | A Django User , which can also be an AnonymousUser . |