avkonst / hookstate

The simple but very powerful and incredibly fast state management for React that is based on hooks
https://hookstate.js.org
MIT License
1.66k stars 109 forks source link

Tried upgrading but validation not working in 4.0.0-rc21 #345

Closed dioptre closed 1 year ago

dioptre commented 2 years ago

Using validation breaks the app in 4.0.0-rc21

I use: const login = useHookstate("", validation())

And get the following trace:

×
1 of 3 errors on the page
TypeError: _b.onInit is not a function
Store
node_modules/@hookstate/core/src/index.ts:1027:19

  1024 |            this._promise = new Promise<StateValueAtRoot>(resolve => {
  1025 |                this._promiseResolver = resolve;
  1026 |            })
> 1027 |            return;
       |                  ^  1028 |        }
  1029 | 
  1030 |        promise = promise

createStore
node_modules/@hookstate/core/src/index.ts:2040

  2037 |     promiseDetector: (p) => Promise.resolve(p) === p,
  2038 |     hiddenInterceptDependencyListsModeDebug: false
  2039 | }
> 2040 | // TODO document
  2041 | export function configure(config: Partial<Configuration>) {
  2042 |     configuration = {
  2043 |         interceptDependencyListsMode: config.interceptDependencyListsMode ?? configuration.interceptDependencyListsMode,

initializer
node_modules/@hookstate/core/src/index.ts:763:34

  760 |         state: state
  761 |     }
  762 | }
> 763 | const [value, setValue] = React.useState(initializer);
      |                          ^  764 | value.state.reconstruct(
  765 |     RootPath,
  766 |     value.store.get(RootPath),

mountState
node_modules/react-dom/cjs/react-dom.development.js:16986:19

  16983 | 
  16984 | if (typeof initialState === 'function') {
  16985 |   // $FlowFixMe: Flow doesn't like mixed types
> 16986 |   initialState = initialState();
        |                 ^  16987 | }
  16988 | 
  16989 | hook.memoizedState = hook.baseState = initialState;

useState
node_modules/react-dom/cjs/react-dom.development.js:17699:15

  17696 | ReactCurrentDispatcher$1.current = InvalidNestedHooksDispatcherOnMountInDEV;
  17697 | 
  17698 | try {
> 17699 |   return mountState(initialState);
        |         ^  17700 | } finally {
  17701 |   ReactCurrentDispatcher$1.current = prevDispatcher;
  17702 | }

useState
node_modules/react/cjs/react.development.js:1622:20

  1619 | }
  1620 | function useState(initialState) {
  1621 |   var dispatcher = resolveDispatcher();
> 1622 |   return dispatcher.useState(initialState);
       |                    ^  1623 | }
  1624 | function useReducer(reducer, initialArg, init) {
  1625 |   var dispatcher = resolveDispatcher();

useHookstate
http://localhost:1234/index.ab6d2328.js:32785:45
Login
packages/www/src/components/Login/index.jsx:51:29

  48 | const globalState = useGlobalState()
  49 | const loginState = useLoginState();
  50 | const realtime = useContext(RealtimeContext);
> 51 | const login = useHookstate(globalState.Mocks?.Login?.Username?.get() || "", validation())
     |                           ^  52 | const password = useHookstate(globalState.Mocks?.Login?.Password?.get() || "")
  53 | 
  54 | //login.validate(p => validateEmail(p), 'Enter a valid email');

renderWithHooks
node_modules/react-dom/cjs/react-dom.development.js:16305:27

  16302 |   }
  16303 | }
  16304 | 
> 16305 | var children = Component(props, secondArg); // Check if there was a render phase update
        |                         ^  16306 | 
  16307 | if (didScheduleRenderPhaseUpdateDuringThisPass) {
  16308 |   // Keep rendering in a loop for as long as render phase updates continue to

mountIndeterminateComponent
node_modules/react-dom/cjs/react-dom.development.js:20074:12

  20071 | 
  20072 |   setIsRendering(true);
  20073 |   ReactCurrentOwner$1.current = workInProgress;
> 20074 |   value = renderWithHooks(null, workInProgress, Component, props, context, renderLanes);
        |          ^  20075 |   hasId = checkDidRenderIdHook();
  20076 |   setIsRendering(false);
  20077 | }

beginWork
node_modules/react-dom/cjs/react-dom.development.js:21587:15

  21584 | switch (workInProgress.tag) {
  21585 |   case IndeterminateComponent:
  21586 |     {
> 21587 |       return mountIndeterminateComponent(current, workInProgress, workInProgress.type, renderLanes);
        |             ^  21588 |     }
  21589 | 
  21590 |   case LazyComponent:

callCallback
node_modules/react-dom/cjs/react-dom.development.js:4164:13

  4161 | function callCallback() {
  4162 |   didCall = true;
  4163 |   restoreAfterDispatch();
> 4164 |   func.apply(context, funcArgs);
       |       ^  4165 |   didError = false;
  4166 | } // Create a global error event handler. We use this to capture the value
  4167 | // that was thrown. It's possible that this error handler will fire more

invokeGuardedCallbackDev
node_modules/react-dom/cjs/react-dom.development.js:4213:15

  4210 | // errors, it will trigger our global error handler.
  4211 | 
  4212 | evt.initEvent(evtType, false, false);
> 4213 | fakeNode.dispatchEvent(evt);
       |         ^  4214 | 
  4215 | if (windowEventDescriptor) {
  4216 |   Object.defineProperty(window, 'event', windowEventDescriptor);

invokeGuardedCallback
node_modules/react-dom/cjs/react-dom.development.js:4277:30

  4274 | function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
  4275 |   hasError = false;
  4276 |   caughtError = null;
> 4277 |   invokeGuardedCallbackImpl$1.apply(reporter, arguments);
       |                              ^  4278 | }
  4279 | /**
  4280 |  * Same as invokeGuardedCallback, but instead of returning an error, it stores

beginWork$1
node_modules/react-dom/cjs/react-dom.development.js:27451:28

  27448 | } // Run beginWork again.
  27449 | 
  27450 | 
> 27451 | invokeGuardedCallback(null, beginWork, null, current, unitOfWork, lanes);
        |                      ^  27452 | 
  27453 | if (hasCaughtError()) {
  27454 |   var replayError = clearCaughtError();

performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:26557:11

  26554 | 
  26555 | if ( (unitOfWork.mode & ProfileMode) !== NoMode) {
  26556 |   startProfilerTimer(unitOfWork);
> 26557 |   next = beginWork$1(current, unitOfWork, subtreeRenderLanes);
        |         ^  26558 |   stopProfilerTimerIfRunningAndRecordDelta(unitOfWork, true);
  26559 | } else {
  26560 |   next = beginWork$1(current, unitOfWork, subtreeRenderLanes);

workLoopSync
node_modules/react-dom/cjs/react-dom.development.js:26466:22

  26463 | function workLoopSync() {
  26464 |   // Already timed out, so perform work without checking if we need to yield.
  26465 |   while (workInProgress !== null) {
> 26466 |     performUnitOfWork(workInProgress);
        |                      ^  26467 |   }
  26468 | }
  26469 | 

renderRootSync
node_modules/react-dom/cjs/react-dom.development.js:26434:6

  26431 | 
  26432 | do {
  26433 |   try {
> 26434 |     workLoopSync();
        |    ^  26435 |     break;
  26436 |   } catch (thrownValue) {
  26437 |     handleError(root, thrownValue);

performConcurrentWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js:25738:73

  25735 | 
  25736 | 
  25737 | var shouldTimeSlice = !includesBlockingLane(root, lanes) && !includesExpiredLane(root, lanes) && ( !didTimeout);
> 25738 | var exitStatus = shouldTimeSlice ? renderRootConcurrent(root, lanes) : renderRootSync(root, lanes);
        |                                                                       ^  25739 | 
  25740 | if (exitStatus !== RootInProgress) {
  25741 |   if (exitStatus === RootErrored) {

workLoop
node_modules/scheduler/cjs/scheduler.development.js:266:42

  263 | currentPriorityLevel = currentTask.priorityLevel;
  264 | var didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
  265 | 
> 266 | var continuationCallback = callback(didUserCallbackTimeout);
      |                                    ^  267 | currentTime = exports.unstable_now();
  268 | 
  269 | if (typeof continuationCallback === 'function') {

flushWork
http://localhost:1234/index.ab6d2328.js:27265:20

  27262 |         throw error;
  27263 |     }
  27264 |     else // No catch in prod code path.
> 27265 |     return workLoop(hasTimeRemaining, initialTime);
        |            ^  27266 | } finally{
  27267 |     currentTask = null;
  27268 |     currentPriorityLevel = previousPriorityLevel;

performWorkUntilDeadline
node_modules/scheduler/cjs/scheduler.development.js:533:20

  530 | var hasMoreWork = true;
  531 | 
  532 | try {
> 533 |   hasMoreWork = scheduledHostCallback(hasTimeRemaining, currentTime);
      |                ^  534 | } finally {
  535 |   if (hasMoreWork) {
  536 |     // If there's more work, schedule the next message event at the end

This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.  Click the 'X' or hit ESC to dismiss this message.
avkonst commented 2 years ago

what is the version of the core package? it should be aligned... I have tried it in unit tests and it works fine.

avkonst commented 2 years ago

could you please provide a reproducer in a code playground online or in a repo?

dioptre commented 2 years ago

Do you have a template playground to start with? It will be very hard for me to extricate all the code from my app.

avkonst commented 2 years ago

you can fork the repo and find the app in docs/demos/todo-list folder. commit in your fork and let me know

avkonst commented 1 year ago

please reopen with more information provided