effector icon indicating copy to clipboard operation
effector copied to clipboard

StoreWritable.on() reports `undefined` returned from reducer

Open Vovan-VE opened this issue 1 year ago • 3 comments

What is the current behavior:

StoreWritable.on() reports undefined returned from the reducer. This doesn't look as intended behavior neither from v23 release notes, nor from documentation.

store: undefined is used to skip updates. To allow undefined as a value provide explicit { skipVoid: false } option

https://share.effector.dev/007a4LsA

const add = createEvent<number | undefined>();
const $v = createStore(0)
  .on(add, (a, b) => {
    if (b !== undefined) {
      return a + b;
    }
  })
  .watch((v) => console.log(">> $s", v));
add.watch((v) => console.log(">> add", v));

add(50);
add();
add(-8);

Docs:

Store

Store is an object that holds the state value. Store is getting updates when receives a value that is not equal (!==) to current one and to undefined.

$store.on(trigger, reducer);

A store cannot hold an undefined value. If a reducer function returns undefined, the store will not be updated.

Release notes:

  • Deprecate undefined as magical value to skip store updates, use skipVoid: true option in combine and map to enable old behavior.

What is the expected behavior:

Using undefined return value from on() reducer looks still fine from docs and release notes, so:

  • either no error should be reported
  • either docs should describe better the undefined status for Store

Which versions

  • Effector 23.0.0

Vovan-VE avatar Dec 16 '23 16:12 Vovan-VE

It’s an option 2: .on docs should explicitly say about undefined as a return value like in .map and combine, we’ll update it, thanks for reporting 👍

zerobias avatar Dec 16 '23 22:12 zerobias

From the docs,

A store cannot hold an undefined value. If a reducer function returns undefined, the store will not be updated

I'd also like to conditionally update the store, so sometimes an on reducer will return void/undefined:

const $user = createStore(null);
const handlePushTokenChangeFx = createEffect(async () => {
	if (1 + 1 === 2) {
		return null;
	}
	return {
		pushToken: 'some-token';
	}
});

$user.on(handlePushTokenChangeFx.doneData, (user, result) => {
	if (user && result?.pushToken) {
		return {
			...user,
			pushToken: result.pushToken,
		};
	}
});

However, I get console errors:

ERROR: store: undefined is used to skip updates. To allow undefined as a value provide explicit { skipVoid: false } option

How can I suppress this message?

mkhoussid avatar Dec 22 '23 12:12 mkhoussid

How can I suppress this message?

$user.on(handlePushTokenChangeFx.doneData, (user, result) => {
	if (user && result?.pushToken) {
		return {
			...user,
			pushToken: result.pushToken,
		};
	}
	
	// just return the same object
	return user
});

sergeysova avatar Dec 28 '23 08:12 sergeysova