question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

something confused me about Provider initialValues and scope

See original GitHub issue

图片 图片

I’m trying to seperate my project into several independent modules, and each module should be wrapped under the Provider and each module has its own atoms the sub component tree cares about. the main structure would look like below: App |- ProviderRoot |-|- ProviderA |- |- |- SubTreeA |- |- ProviderB |- |- |- SubTreeB

// atom1/atom2/atom3 would only be used in SubTreeA const atom1 = atom(); const atom2 = atom(); const atom3 = atom();

// atom4/atom5/atom6 would only be used in SubTreeB const atom1 = atom(); const atom1 = atom(); const atom1 = atom();

// atom7 can be used in both SubTreeA and SubTreeB

the code is like this:

import { Provider, atom, useAtom } from 'jotai';

const atom1 = atom('');
const atom2 = atom('');
const atom3 = atom('');
const atom4 = atom('');
const atom5 = atom('');
const atom6 = atom('');
const atom7 = atom('');

export default function App() {
  return (
    <Provider>
      <ModuleA />
      <ModuleB />
    </Provider>
  );
}

function ModuleA() {
  return (
    <Provider>
      <SubTreeA />
    </Provider>
  );
}


function ModuleB() {
  return (
    <Provider>
      <SubTreeB />
    </Provider>
  );
}

function SubTreeA() {
  const [value1, setValue1] = useAtom(atom1);
  const [value2, setValue2] = useAtom(atom2);
  const [value3, setValue3] = useAtom(atom3);
  const [value7, setValue7] = useAtom(atom7); // this should be allowed
  const [value6, setValue6] = useAtom(atom6);// this should be forbidden

  return (
    <div>
    <div>value1: {value1}</div>
    <div>value2: {value2}</div>
    <div>value3: {value3}</div>
    <div>value7: {value7}</div>
    </div>
  );
}

function SubTreeB() {
  const [value4, setValue4] = useAtom(atom4);
  const [value5, setValue5] = useAtom(atom5);
  const [value6, setValue6] = useAtom(atom6);
  const [value7, setValue7] = useAtom(atom7); // this should be allowed
  const [value1, setValue1] = useAtom(atom1); // this should be forbidden
  return (
    <div>
    <div>value4: {value4}</div>
    <div>value5: {value5}</div>
    <div>value6: {value6}</div>
    <div>value7: {value7}</div>
    </div>
  );
}

I tried to give the different Provider different scope, but it doesn’t work at all.

Is there any way that I can achieve my goal? my main target is to make each module unrelyable. ModuleA shouldn’t care about anything in MouduleB, and vice versa. Those atoms that can be used in all the modules must be passed by the Provider above all the modules.

in my very first idea, I think scope can do this, which is what scope mean, it means boundary, gap. but as the doc says, scope is for library use. and I tried scope in my code, it doesn’t prevent me from using an atom with different scope from the one in Provider:

<Provider scope={scope1}>
    <Component />
</Provider>

const Component = () => {
  const [value, setValue] = useAtom(atom1, scope2); // notice the scope is different
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:16 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Thisencommented, Sep 16, 2021

@chj-damon There’s a different option aswell:

const ScopeGuardContext = createContext<Scope | null>(null)

function createScopedAtomHook(scope: Scope) {
  return (atom: Parameters<typeof useAtom>[0]) => {
    const currentScope = useContext(ScopeGuardContext)
    if (scope !== currentScope) {
      throw Error('Wrong scope')
    }
    return useAtom(atom)
  }
}

// ...

const useScopedAtom = createScopedAtomHook(myScope)

function SubTreeA(props) {
  return (
    <ScopeGuardContext.Provider value={myScope}>
      <MyComponent />
    </ScopeGuardContext.Provider>
  );
}

function MyComponent() {
  const [value] = useScopedAtom(atom1)
  // ...
}

createScopedAtomHook creates a useAtom hook, but it guards against not using the correct scope. There’s a codesandbox for the pattern here: https://codesandbox.io/s/next-js-with-custom-babel-config-forked-bp6qs?file=/pages/index.js

0reactions
Thisencommented, Sep 16, 2021

Im not sure I understand global atoms then.

Read more comments on GitHub >

github_iconTop Results From Across the Web

something confused me about Provider initialValues and scope
I'm trying to seperate my project into several independent modules, and each module should be wrapped under the Provider and each module has ......
Read more >
Redux form - loading initiaValues from state, all within a single ...
I've figured out how to prepopulate those forms inside of the reduxForm().connect stuff, however I can't seem to get the form to populate...
Read more >
Where to Initialize State in React - Dave Ceddia
It can be confusing. Do you put the state = {...} directly inside the class, or do you write a constructor and say...
Read more >
The last guide to the useEffect Hook you'll ever need
Understanding how the useEffect Hook works, and why it requires a wholesale shift in mindset, is essential to writing modern React code.
Read more >
Flutter - Provider - Points of interest - Points to care about
The initial objective of a Provider is, as its name indicates, to provide something to whoever would need to have access to it....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found