Skip to content
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

A molecule that doesn't depend on anything was created twice (React strict mode) #58

Open
disjukr opened this issue May 21, 2024 · 3 comments

Comments

@disjukr
Copy link

disjukr commented May 21, 2024

According to the documentation, a molecule that does not depend on any other molecule or scope should be created only once.

  • A molecule without any dependencies or scopes will return a single value.

However, I found that the molecule created twice in the code below. (StackBlitz)

The screen after few clicks

import React from 'react';
import ReactDOM from 'react-dom/client';
import { createScope, molecule, use } from 'bunshi';
import { ScopeProvider, useMolecule } from 'bunshi/react';

const FooMolecule = molecule(() => {
  console.log('it should be logged once'); // logged twice with few button clicks
  return Math.random();
});

const BarScope = createScope(null);
const BarMolecule = molecule(() => {
  const foo = use(FooMolecule);
  const bar = use(BarScope);
  return { foo, bar };
});

function MyComponent() {
  const { foo, bar } = useMolecule(BarMolecule);
  return (
    <div>
      foo: {foo}
      <br />
      bar: {bar}
    </div>
  );
}

function Main() {
  const [count, setCount] = React.useState(1);
  return (
    <>
      <button onClick={() => setCount((c) => c + 1)}>+</button>
      {Array.from({ length: count }, (_, k) => k).map((v) => (
        <ScopeProvider key={v} scope={BarScope} value={v}>
          <MyComponent />
        </ScopeProvider>
      ))}
    </>
  );
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Main />
  </React.StrictMode>
);
@loganvolkers loganvolkers changed the title A molecule that doesn't depend on anything was created twice A molecule that doesn't depend on anything was created twice (React strict mode) May 22, 2024
@loganvolkers
Copy link
Member

@disjukr this is related to React strict mode.

If you remove <React.StrictMode> from your root, you'll notice it only logs once.

There are some docs specifically on this behaviour: https://www.bunshi.org/concepts/lifecycle/#react-strict-mode

There are a couple possibilities here:

  1. Bunshi could do a better job of handling this case in strict mode
  2. Due to limitations in Strict mode, this behaviour is stuck

If you want a workaround, you can use your FooMolecule in a root component, for example: https://stackblitz.com/edit/vitejs-vite-6pu5em?file=src%2Fmain.tsx
image

@loganvolkers
Copy link
Member

This could possibly be related to #64

@shredor
Copy link

shredor commented Aug 8, 2024

Hi! I simplified code to reproduce this bug StackBlitz
image

import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
import { molecule, use } from 'bunshi';
import { useMolecule } from 'bunshi/react';

const FooMolecule = molecule(() => {
  console.log('it must be logged once');
  return Math.random();
});

const BarMolecule = molecule(() => {
  const foo = use(FooMolecule);
  return { bar: foo };
});

function Main() {
  const [isFooVisible, setIsFooVisible] = useState(false);
  return (
    <>
      <button onClick={() => setIsFooVisible(true)}>+</button>
      {isFooVisible ? <Foo /> : <div>foo placeholder</div>}
      <Bar />
    </>
  );
}

function Foo() {
  const foo = useMolecule(FooMolecule);
  return <div>foo: {foo}</div>;
}

function Bar() {
  const { bar } = useMolecule(BarMolecule);
  return <div>bar: {bar}</div>;
}

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Main />
  </React.StrictMode>
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants