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

[Question] Is there any way to create a readonly focusAtom? And is it possible to make it work with atomWithImmer? #450

Closed
yf-hk opened this issue Apr 25, 2021 · 5 comments

Comments

@yf-hk
Copy link

yf-hk commented Apr 25, 2021

For example here's my atoms:

const pagesAtom = atom([{
  children: ['element 1', 'element 2'],
}]);
const currentPageAtom = atom(0);
const currentPageElementsAtom = atom(get => get(pagesAtom)[get(currentPageAtom)].children);
const { index } = props;
const currentElementAtom = focusAtom(currentPageElementsAtom, optic => optic.nth(index)));

However since first parameter should be a WritableAtom so it doesn't work. How about implementing something like focusAtomValue and updateFocusAtom to dress this issue?

Also I found that atoms created by atomWithImmer couldn't be used by focusAtom. I can manually use immer to do the samething in the original atom, but is there a better way to do it?

@dai-shi
Copy link
Member

dai-shi commented Apr 25, 2021

focusAtom only works for symmetric writable atoms. selectAtom works for readonly atoms.

You can do it natively too.

  // in a component
  const { index } = props;
  const currentElementAtom = useAtom(useMemo(() => atom((get) => get(currentPageElementsAtom)[index]), [index]));

Or, you can try to make currentPageElementsAtom writable with focusAtom.
To use focusAtom in render with props, you need to use useCallback.

  // in a component
  const { index } = props;
  const currentElementAtom = focusAtom(currentPageElementsAtom, useCallback((optic) => optic.nth(index), [index])));

btw, I assume pagesAtom, currentPageAtom and currentPageElementsAtom are defined outside render.


atomWithImmer is currently not compatible with WritableAtom<Value, Value>.
We might be able to improve atomWithImmer to accept Value on write as well, and it could be used with focusAtom. Anyone wants to work on it?

@yf-hk yf-hk changed the title [Question] Is there anyway to create a readonly focusAtom? And is it possib to make it work with atomWithImmer? [Question] Is there any way to create a readonly focusAtom? And is it possible to make it work with atomWithImmer? Apr 25, 2021
@yf-hk
Copy link
Author

yf-hk commented Apr 26, 2021

@dai-shi Thanks very much for your quick response. This library is amazing, it's very easy to use and I can see you put a lot of effort in maintaining it.
Your solution works great for me.

@dai-shi
Copy link
Member

dai-shi commented Apr 26, 2021

So, you solved with the readonly approach? Nice.

Closing this as #452 is filed.

Thanks for using the lib. Feel free to report more issues.

@dai-shi dai-shi closed this as completed Apr 26, 2021
@yf-hk
Copy link
Author

yf-hk commented Apr 26, 2021

@dai-shi Well, I solved the readonly issue but not atomWithImmer one. I tried to dig a bit into it to see if I can create a PR, but it turned out that it's a bit complicated than I thought. Hopefully someone else can work on it to make it more universal.

@dai-shi
Copy link
Member

dai-shi commented Apr 26, 2021

Well, the code for #452 would actually be a few lines.

  (get, set, arg) => {
    if (typeof arg === 'function') {
      set(anAtom, produce(get(anAtom), arg)
    } else {
      set(anAtom, arg)
    }
  }

But, types, tests, and docs wouldn't be trivial.

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

No branches or pull requests

2 participants