-
-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setKeys method on store #110
Comments
Our current policy is to use helper functions to all syntax sugar. Something like: Without this policy, we will not be able to be nano library with extremely small footprint. Is it OK for you? We can add |
@ai there is one interesting thing: Or it might push to use |
I disagree of “unexpected behavior.” For instance, |
*Update: I found the map store: I think doing this everywhere is crazy:
For developer experience this is not great at all. I cannot see why you do not have a method that allows updates, so we can do this: cart.update({key: 'value'})
// or
cart.update({key: 'value', key2: 'value2'})
// or
cart.update(someUpdatedData) That is more natural then I understand you are talking about nanostores footprint but come on, the above request is standard coding practice that every developer will use. My store is bloated is .set(), .get(), ...destructure and the bloat in my own code alone from your design decision far outweighs the 5 lines of code you need to add to create an update method. |
https://stackblitz.com/edit/vitejs-vite-qjgnio?file=main.js&terminal=dev I have a similar issue I created a const session = map({ isLogged: false, isLogging: false, user: undefined });
session.listen((value, key) => {
if (key === 'isLogged') {
console.log('isLogged', value.isLogged);
}
}); Using When a reset the store using I could check for undefined also but it can occurs to trigger the change even if the desired key does not change const session = map({ isLogged: false, isLogging: false, user: undefined });
session.listen((value, key) => {
if (key === 'isLogged' || key === undefined) {
console.log('isLogged', value.isLogged);
}
});
// console.log will be called 3 times even if 'isLogged' does not change
session.set({ isLogged: false, isLogging: false, user: undefined });
session.set({ isLogged: false, isLogging: true});
session.set({ isLogged: false, isLogging: true, user: 'xxx'}); An API like map#reset that trigger appropriate change events for each key changed would allow to do a more fined tracking |
@blikblum you can use import { listenKeys } from 'nanostores'
listenKeys(session, ['isLogged'], () => {
console.log('isLogged', value.isLogged)
})
Changed key is just a small optimization. It is a way to reduce callbacks call a little. Do you have a real use case, when callback have to be called only on value changed? |
I've hit the described issue (listening to a key not triggering when store is updated) twice: I load the app config when store is started and set to a map store. The idea is to have appConfig store as source of truth and derives other config stores like insurances from it const initialValue = {}
export const appConfig = map(initialValue)
export const updateConfig = action(appConfig, 'updateConfig', (store, { key, value }) => {
store.setKey(key, value)
})
let configLoaded = false
onStart(appConfig, async () => {
if (!configLoaded) {
const platform = await getPlatform()
const dir = platform === 'win32' ? BaseDirectory.LocalData : BaseDirectory.Config
const configFileName = await join('auto-fisio-invoice', 'config.json')
const configExists = await exists(configFileName, {
dir,
})
if (configExists) {
const content = await readTextFile(configFileName, {
dir,
})
const appConfigData = JSON.parse(content)
appConfig.set(appConfigData)
configLoaded = true
}
}
}) Then i listen to insurances key and update a second store: export const insurances = atom([])
appConfig.listen((value, key) => {
if (key === 'insurances' || key === undefined) {
setInsurances(value.insurances)
}
})
export const setInsurances = action(insurances, 'setInsurances', (store, value) => {
store.set(value)
return value
}) The first time i wrote the code, i did not added the key === undefined check and the insurances store was not initialized. My reasoning is that the 'insurances' value changed after loading the data so i was expecting to listener be called with each key whose value changed |
It will be very bad for performance. Key listening is a rare feature which is not very affective (better for optimization is to create a |
Performance here is not an issue since is triggered once in a while. DX is more important which seems the whole point of |
@blikblum the way for better DX is just not using |
There's another use case (i think i had posted earlier) that i hit when using A auth session store import { GoogleAuthProvider, getAuth, onAuthStateChanged, signInWithPopup } from 'firebase/auth'
import { session } from '../stores/session.js'
const auth = getAuth()
export function startSession() {
session.setKey('isLogging', !!localStorage.getItem('hasCredential'))
onAuthStateChanged(auth, async (user) => {
if (user) {
localStorage.setItem('hasCredential', true)
const { displayName: name, uid: id, email } = user
session.setKey('user', { id, name, email })
session.setKey('isLogged', true)
session.setKey('isLogging', false)
} else {
localStorage.removeItem('hasCredential')
session.set({ isLogged: false, isLogging: false, loginError: undefined, user: undefined })
}
})
}
export async function signIn() {
session.setKey('isLogging', true)
try {
const provider = new GoogleAuthProvider()
provider.setCustomParameters({
prompt: 'select_account',
})
await signInWithPopup(auth, provider)
} catch (error) {
session.setKey('isLogged', false)
session.setKey('isLogging', false)
session.setKey('loginError', {
title: 'Erro ao autenticar usuário',
content: `${error}`,
})
}
}
export async function signOut() {} I wrote a listener to isLogged state to update ui accordingly export function onLogged(callback) {
session.subscribe((value, key) => {
if (key === 'isLogged' ) {
callback(value)
}
})
} But there's a bug at line: If i want to keep setKey functionality i have to change the reset code to: session.setKey('isLogged', false)
session.setKey('isLogging', false)
session.setKey('user',undefined)
session.setKey('loginError',undefined) |
I would advocate for a Presumably one of the great parts of this library is I believe that when we reach a point where a small API addition prevents the library from being used it's critical to add that extra functionality. On another note, I would imagine the requests in regards to |
Hi @ai . Did you eventually add the helper function "addKeys" to the library ? In the interest of keeping the library as light weight , It would be nice to have this . |
No, feel free to open PR |
First off, Thank you guys for this library. I wanted to ask if you can possibly include a setKeys (on the map store) method that internally simply does
or in the map store define this function
or a function that also handles deeply nested objects (like lodash-es merge method).
I can't say how performant or not the second option is, but it leverages the checks done in setKey method.
Or if there is a way to create an extension on the store that adds this, kindly point that to me. This will help reduce overall the lines of code one has to write as more often that not, we are partially updating the store , and setKey only does a key at a time.
The text was updated successfully, but these errors were encountered: