Link to example:
https://github.com/LXSMNSYC/scoped-model/tree/master/examples/preact-scoped-model
Sandbox:
https://codesandbox.io/s/musing-spence-45g0y
console.log('First call', useState(0));
const [count, setCount] = useState(initialCount ?? 0);
console.log('Next call', useState(0));
const increment = useCallback(() => {
setCount((c) => {
console.log('Current State', c);
return c + 1;
});
}, []);
const decrement = useCallback(() => {
setCount((c) => {
console.log('Current State', c);
return c - 1;
});
}, []);
yarn at the root.yarn dev. setState should be able to receive the current state.useState returns 'true' instead of the state and the setState function.
setState call receives an undefined state.
preact@^10.4.8vite@^1.0.0-rc.4I can't get it to build, it seems like there's a lot of building for the core package, ... to do that fails as well.
I can't get it to build, it seems like there's a lot of building for the core package, ... to do that fails as well.
may I see the logs?
I just tried this in my own example where everything is working correctly. Wondering if this has to do with Suspense.
[vite] Build errored out.
[Error: Could not load @pika/react/source.development.js (imported by src\Index.bs.js): ENOENT: no such file or directory, open 'C:\Users\jovid\Desktop\scoped-model\examples\re-scoped-model-vite\@pika\react\source.development.js'] {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\Users\\jovid\\Desktop\\scoped-model\\examples\\re-scoped-model-vite\\@pika\\react\\source.development.js',
watchFiles: [
'C:\\Users\\jovid\\Desktop\\scoped-model\\examples\\re-scoped-model-vite\\index.html',
'C:\\Users\\jovid\\Desktop\\scoped-model\\examples\\re-scoped-model-vite\\src\\Index.bs.js',
'@pika/react/source.development.js'
]
}
And
[vite] Failed to resolve module import "@lxsmnsyc/preact-scoped-model/dist/preact-scoped-model.esm.js". (imported by /src/App.tsx)
[vite] Failed to resolve module import "@lxsmnsyc/preact-scoped-model/dist/preact-scoped-model.esm.js". (imported by /src/App.tsx)
[vite] Failed to resolve module import "@lxsmnsyc/preact-scoped-model/dist/preact-scoped-model.esm.js". (imported by /src/App.tsx)
Because of the above build failure I assume
Hmm, I think I missed something with the project setup, can you try running 'yarn bootstrap' and see if everything works out? If not, I might try creating a separate example instead.
@JoviDeCroock I have provided a CodeSandbox link, please check it out
Seems like there's something inside of the preact-scoped-model library happening that manipulates the value returned (somehow). When I add useState(0) just in App it works correctly, it's when we enter the createModel function that something seems to manipulate the current vnode in question.
@JoviDeCroock this is actually what's inside that runs the createModel argument:
const ProcessorInner: FunctionComponent<Props> = (props) => {
const emitter = useContext(context);
if (!emitter) {
throw new MissingScopedModelError(displayName);
}
const model = useModelHook(props as Props);
emitter.sync(model);
useIsomorphicEffect(() => {
emitter.consume(model);
}, [emitter, model]);
return null;
};
I assume that it should work correctly? Given that 1:1 code was implemented in React.
@LXSMNSYC It might have something to do with how Vite optimizes the dependencies. Try excluding it:
const config: UserConfig = {
jsx: {
factory: 'h',
fragment: 'Fragment'
},
optimizeDeps: {
exclude: [
'@lxsmnsyc/preact-scoped-model',
],
},
plugins: [preactRefresh()],
};
@havelaer I have tried excluding it and still yields the same result. It is weird that a 1:1 implementation with my React version yields a different result for Preact. useState returning true makes it even more weirder.
@LXSMNSYC I encountered the same problem, also with the first useState() returning true, that's how I found this issue.
I finally fixed it by adding a dependency to optimizeDeps.exclude.
I just checked out your repository and ran scoped-model/examples/preact-scoped-model yielding the result you described above. And excluding @lxsmnsyc/preact-scoped-model from optimizeDeps in examples/preact-scoped-model/vite.config.ts actually fixes it on my machine.
So what happens, I think, is that when vite optimizes @lxsmnsyc/preact-scoped-model which has a dependency of preact and preact/hooks is that it bundles the preact/hooks code into an "optimized" preact-scoped-model bundle resulting in dubbel monkey patching preact's internal options._render, options.diffed, options._commit and options.unmount.
Check out line 3 of http://localhost:3000/@modules/@lxsmnsyc/preact-scoped-model.js in you network tab when running your example, that's minified preact/hooks code.
It would be nice if preact/hooks could be guarded against monkey patching the options object more than once.
@havelaer Thanks for the feedback. That's what I noticed too, aside from the fact that I had problems when Vite (namely, ESBuild) tries to import Preact through import default, leading to a module resolution error.
I am still unsure which is at fault here.
I donβt think this is our fault, it works in other bundlers. Essentially we could implement something that prevents double injection but the code is still included duplicated which is never a good thing.
We are relying on default resolution behaviour where it deduplicates.
A reason for this error however could be a lot of mixed imports within this lib code itself and the bundler used to produce the dist.
Maybe scoped-model should limit itself to only Preact and Preact/hooks imports for a Preact specific version?
Agree with @JoviDeCroock . This issue to me sounds like a bug in vite. Duplicating dependencies is most of the time a dangerous endeavour if done incorrectly. This issue should be filed upstream in the vite tracker as it's not an issue with Preact.
Thanks for the response @JoviDeCroock.
I'll close this for now. I'll be trying out other JS bundlers and see if the problem still persists.
Most helpful comment
I donβt think this is our fault, it works in other bundlers. Essentially we could implement something that prevents double injection but the code is still included duplicated which is never a good thing.
We are relying on default resolution behaviour where it deduplicates.
A reason for this error however could be a lot of mixed imports within this lib code itself and the bundler used to produce the dist.
Maybe scoped-model should limit itself to only Preact and Preact/hooks imports for a Preact specific version?