将函数作为 Jotai 原子存储?

3

我想知道是否可以将一个函数存储为jotai原子,并且如果可以,如何实现。当状态的值是数组时,简单地复制创建和使用jotai原子状态的标准模式是可行的,但当状态的值是一个函数时,这种方法就不起作用了。

"./jotaiStore.js"

import { atom } from "jotai";

function test(x) {return x + 4;}
let testa = atom(test);
export { testa }; 

./App.js

import { testa } from "./jotaiStore.js";
import { useAtom } from "jotai";

export default function App() {
  
  const [locTest, locSetTest] = useAtom(testa);
  console.log(locTest);
  console.log(locTest(1));

  return (
    <div className="App">
    </div>
  );
}

请参见https://codesandbox.io/s/thirsty-brook-n1ucjr?file=/src/App.js:24-493console.log(locTest)的结果如下:
function (a) {
        dependencies.add(a);
        var aState = a === atom ? getAtomState(version, a) : readAtomState(version, a);

        if (aState) {
          if ('e' in aState) {
            throw aState.e;
          }

          if ('p' in aState) {
            throw aState.p;
          }

          return aState.v;
        }

        if (hasInitialValue(a)) {
          return a.init;
        }

        throw new Error('no atom init');
      }4 

console.log(locTest(1))会生成错误“locTest不是函数”。

编辑:我找到了一种将函数存储为jotai状态的方法(请参见下文),但不知道如何更新。如果有其他人有更好的可更新解决方案,我仍然非常感兴趣。

3个回答

2

我已经找到了解决方案,可以满足我个人的需求,也许对你的实现有所帮助。

这个想法是创建Jotai状态和派生状态。后者将包含您想要在应用程序中共享的函数逻辑。您可以通过设置Jotai状态来触发它,从而启动派生状态中的代码。

代码类似于:

store.js

import { atom } from 'jotai'

export const stateAtom = atom(1)
export const derivedStateAtom = atom(get => get(stateAtom) + 4)

无论您在哪里触发函数:

Component1.js

import { useAtom } from 'jotai'
import { stateAtom } from '../store'

export default function Component1() {

  const [ , setState ] = useAtom(stateAtom)

  // pass the argument of function
  setState(x)

  ...
}

无论您想在何处获得函数的结果:

Component2.js

import { useAtom } from 'jotai'
import { derivedStateAtom } from '../store'

export default function Component2() {

  // "derivedState" will be the result of your function
  const [ derivedState ] = useAtom(derivedStateAtom)

  ...
}

如果你有相互依赖的状态,可以使用useEffect并指定它们的依赖关系(只有在一个状态改变后才会对另一个状态进行操作)。


2
不确定你是否还需要这个,但是大石实际上建议将函数封装在一个对象中。
const fnAtom = atom({ fn: () => "your function" })

您可以根据上述原子创建一个派生的可读和/或可写原子。
const doWhateverFnAtom = atom(
  (get) => get(fnAtom),
  (get, set, newFn) => {
    set(fnAtom, { fn: newFn })
  }
)

来源:https://github.com/pmndrs/jotai/discussions/1746#discussioncomment-4872129


1

这篇关于如何在React状态中存储函数的解释https://medium.com/swlh/how-to-store-a-function-with-the-usestate-hook-in-react-8a88dd4eede1似乎也适用于jotai(见下文)。

不幸的是,我还不能使用相同的解释来更新jotai中的函数值状态(当我尝试调整上述链接中描述的更新方法时,我会收到“错误:不可写入原子”)。

"./jotaiStore.js"

import { atom } from "jotai";

function test(x) {return x + 4;}
let testa = atom( 
                  () => x => test(x) 
                );
export { testa }; 

./App.js

import { testa } from "./jotaiStore.js";
import { useAtom } from "jotai";

export default function App() {
  
  const [locTest, locSetTest] = useAtom(testa);
  console.log(locTest);
  console.log(locTest(1));

  return (
    <div className="App">
    </div>
  );
}

请查看https://codesandbox.io/s/loving-architecture-693i76?file=/src/App.js


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接