When server-side rendering your component, Joystick can automatically fetch data from your API, or from a third-party data source. On the client, data can be refetched to update data after the page has loaded.
Example Usage
Fetching Data During SSR
Though the data()
function is defined on your component, it is only ever run in a server-side context. To make this work. Joystick passes an object api
to the data function which contains methods for interacting with your API: api.get()
, api.set()
, and api.fetch()
.
ui/pages/index/index.js
import joystick from '@joystick.js/ui';
const Index = joystick.component({
data: async (api = {}, req = {}, input = {}, instance = {}) => {
return {
books: await api.get('books', {
input: {
category: req?.params?.category,
},
})
};
},
render: ({ data, each }) => {
return `
<div>
<h2>Books</h2>
<ul>
${each(data?.books, (book = {}) => {
return `<li><a href="/books/${book.id}">${book.title}</a> by ${book.author}</li>`;
})}
</ul>
</div>
`;
},
});
export default Index;
Above, we define data
as a function
on our component options. That function takes four possible arguments: api
, req
, input
, and component_instance
.
While we can just return the raw value from a call like api.get('books')
, it’s recommended to organize returned values under named keys so they’re easier to reference in the component.
The input
object passed to api.get()
is often used in tandem with req
, which contains route-specific data like URL parameters. For example, req.params.category
accesses :category
from a route like /books/:category
.
Refetching Data
Once a component is mounted, you can call instance.data.refetch()
to update its data. The refetch()
method accepts an input
object, which maps to the input
argument of the data()
function.
ui/pages/index/index.js
import joystick from '@joystick.js/ui';
const Index = joystick.component({
data: async (api = {}, req = {}, input = {}, instance = {}) => {
return {
books: await api.get('books', {
input: {
category: req?.params?.category,
page: input?.page,
},
})
};
},
events: {
'click [data-page]': (event = {}, instance = {}) => {
instance.data.refetch({
page: parseInt(event.target.getAttribute('data-page'), 10),
});
},
},
render: ({ data, each }) => {
return `
<div>
<h2>Books</h2>
<ul>
${each(data?.books, (book = {}) => {
return `<li><a href="/books/${book.id}">${book.title}</a> by ${book.author}</li>`;
})}
</ul>
<div class="pagination">
<ol>
<li data-page="1">1</li>
<li data-page="2">2</li>
<li data-page="3">3</li>
</ol>
</div>
</div>
`;
},
});
export default Index;
To trigger a refetch, we listen for clicks on elements with a data-page
attribute. When clicked, we extract the page number and pass it to refetch()
via the input
object.
API
Definition
data(api: object, req: object, input: object, component_instance: object) => object;
Parameters
- api object required
-
An object containing methods for interacting with your app's API or third-party data sources.
- fetch function
- A server-safe version of fetch() for calling third-party APIs.
- get function
- A Joystick-specific method to call a getter endpoint in your app's API.
- set function
- A Joystick-specific method to call a setter endpoint in your app's API.
- req object
-
A sanitized copy of the incoming HTTP request for server-rendered components.
- headers object
- The HTTP headers for the request.
- params object
- The route parameters (e.g., from /:slug).
- query object
- The query parameters from the URL.
- context object
-
Additional request context passed in by your app.
- user object
- A browser-safe copy of the currently logged-in user, if available.
- input object
- Optional input variables passed via instance.data.refetch().
- component_instance object
- The current component instance.