Pick Utility
The pick
utility simplifies working with object states by allowing you to read deep property values while keeping the reactivity of the states.
Why use pick
utility?
Let's look at a simple user object state.
const [currentUser] = state(null)
The user data model looks something like this:
interface User {
name: string
emails: string[]
skils: {
name: string
yearsOfExperience: number
}[]
type: 'Admin' | 'User' | 'Partner'
jobs: {
name: string
startingDate: Date
endDate?: Date
company: {
name: string
website: string
logo: string
}
}[]
}
Now we can try to display this user information that was set in the state.
html`
<h3>${currentUser().name}</h3>
<p>email: ${currentUser().email}</h3>
<h4>Skills:</h4>
<ul>${repeat(currentUser().skills, renderSkil)}</ul>
<h4>Jobs:</h4>
<ul>${repeat(currentUser().jobs, renderJob)}</ul>
`.render(document.body)
This displays everything perfectly. However, if this is an object that changes, nothing will re-render because everything was rendered statically. The simple solution is to render everything dynamically using functions.
html`
<h3>${() => currentUser().name}</h3>
<p>email: ${() => currentUser().email}</h3>
<h4>Skills:</h4>
<ul>${repeat(() => currentUser().skills, renderSkil)}</ul>
<h4>Jobs:</h4>
<ul>${repeat(() => currentUser().jobs, renderJob)}</ul>
`.render(document.body)
Alternatively, you can use pick
to pick the properties you want to render from a state.
html`
<h3>${pick(currentUser, 'name')}</h3>
<p>email: ${pick(currentUser, 'email')}</h3>
<h4>Skills:</h4>
<ul>${repeat(pick(currentUser, 'skills'), renderSkil)}</ul>
<h4>Jobs:</h4>
<ul>${repeat(pick(currentUser, 'jobs'), renderJob)}</ul>
`.render(document.body)
The pick
utility is just a function and can be used outside the templates as well.
console.log(pick(currentUser, 'jobs')())
Deep values
The best part of using pick
is its ability to let you pick deep values. For example, let's access our current user third job company website.
html`${pick(currentUser, 'jobs.2.company.website')}`
As you can see, you can use dot notation to access properties deeply and everything will re-render when these values change.
Undefined values
The pick
utility also offers protection against undefined values by preventing things from throwing errors when trying to read a property that does not exist.
The pick
helper will catch the error and simply returns undefined
that can be rendered or read by your code.
html`${pick(currentUser, 'jobs.2.company.url')}`.render(document.body)
// renders "undefined"