Skip to content

Errors and warnings overview

Joachim Bjørge edited this page Jul 18, 2021 · 11 revisions

Errors and warnings overview

core-10

If setState() returns a Promise, an onDone handler (and optionally an onError handler) is required to do any state changes.

Yes:

setState(
    'reason',
    async () => {
        state1.counter++;
        const value = await fetchSomeData();
        return (value % 3 === 0) ? 'hello' : 'howdy';
    },
    value => { state1.greeting = value }, // <-- onDone handler
    error => { state1.errors.push(error.message) } // <-- onError handler
);

No:

setState(
    'reason',
    async () => {
        state1.counter++;
        const value = await fetchSomeData();
        return (value % 3 === 0) ? 'hello' : 'howdy';
    }
)

core-11

State can not be manipulated outside of setState().

Yes:

setState('reason', () => state1.counter++);

setState(
    'reason',
    () => Promise.resolve(state1.counter + 1),
    newCount => { state1.counter = newCount }
)

No:

state1.counter++;
state1.counter = state1.counter + 1;

core-12

If setState() returns a Promise, an onDone handler needs to be provided to further change the state after the promise has resolved (while still in the same setState context).

Yes:

setState(
    'reason',
    async () => {
        state1.counter++;
        const value = await fetchSomeData();
        return (value % 3 === 0) ? 'hello' : 'howdy';
    },
    value => { state1.greeting = value }, // <-- onDone handler
    error => { state1.errors.push(error.message) } // <-- onError handler
);

No:

setState(
    'reason',
    async () => {
        state1.counter++;
        const value = await fetchSomeData();
        state1.greeting = (value % 3 === 0) ? 'hello' : 'howdy';
    }
)
setState(
    'reason',
    async () => {
        state1.counter++;
        const value = await fetchSomeData();
        state1.requestCount++; // <-- state changed after await
        return (value % 3 === 0) ? 'hello' : 'howdy';
    },
    value => { state1.greeting = value }, // <-- onDone handler
    error => { state1.errors.push(error.message) } // <-- onError handler
)

core-13

A call has been made to watchState(_, options) without providing a callback for when state changes.

  • options - options object which describes how to watch the state
    • An error will be thrown if both onChanged and onEachChange are undefined (one of them needs to be set).

core-14

Namespaces must be unique. When Diffx stores your state it does so by having an object with all state in, where the namespace is used as the key, and the state is the value.

createState('myUniqueNamespace', { a: 1 });
createState('my other unique namespace', { b: 1 });

// Diffx will internally store the above as
const rootState = {
    myUniqueNamespace: { a: 1 },
    'my other unique namespace': { b: 1 }
}

If createState is called again with the same namespace, Diffx will throw an error.
If you are developing in e.g. React, the hot reload of the code will automatically call createState with the same namespace again. To avoid throwing, use setDiffxOptions({ devtools: true }).

core-15

If running with setDiffxOptions({ devtools: true }), running createState(namespace) with the same namespace multiple times will trigger a replacement of the state. This is to allow it to work with hot reload, but also to notify in case it was unintended. See core-14 for more info.

core-16

The first argument provided to setState() must be of type string, explaining why the state will be changed.

core-17

The second argument provided to setState() must be of type function, wrapping changes to the state.

setState('incrementing the counter', () => state1.counter++);

core-18

The state has been paused (possibly by selecting a state in the Diffx devtools). Changes to the state are ignored and logged to the console while paused.

core-19

The mutatorFunc provided in setState(reason, mutatorFunc) returned a Promise that threw an error.
To catch the error, an error handler needs to be provided.

setState(
    'Testing an asynchronous throw',
    () => new Promise(() => { throw new Error('I am a promise that threw'); }),
    () => {}, // <-- onSuccess
    error => { /* do something when the error occurs */ }
);

core-20

This error occurs when setState() is nested inside setState() until it reaches the maxNestingDepth set in setDiffxOptions({ maxNestingDepth: <integer> }) (default is 100).

Reaching the max nesting depth is usually caused by watchState calling setState which in turn triggers watchState again, resulting in a loop.

const state1 = createState('my state', { counter: 0 });

// this will result in a loop
watchState(
    () => state1.counter,
    {
        emitInitialValue: true,
        onEachSetState: newValue => {
            setState('increment counter', () => state1.counter++);
        }
    }
);

core-21

This error occurs when persistence has been enabled globally

setDiffxOptions({ persistence: true })

or for a specific state

createState(namespace, initialState, { persistence: true })

without specifying { persistenceLocation }.

The persistenceLocation is expected to have the same API as localStorage/sessionStorage, and is used by Diffx to persist the state.