微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

反应自定义钩子功能不读取反冲原子

如何解决反应自定义钩子功能不读取反冲原子

我正在尝试在 React 项目中使用 formik、typescript 和 recoil 制作一个多请求、多步骤的表单。我创建了一个返回三个函数自定义钩子,其中一个函数需要它正在使用的模型的特定 UUID,以便它可以发出 PUT 请求。当我用另一个相同的钩子函数发出 POST 请求时,这个 UUID 被设置为一个 Recoil Atom,然后我尝试在它下面的函数中访问它,但它没有正确显示。我试图等待它并将它分配给一个变量,但无济于事,当我在函数外记录它时,状态返回我需要的值,但是当我将它记录在函数内部时(我需要它的位置),它是空的。而且我试图避免使用 localstorage,因为这意味着需要管理另一种类型的数据,这可能会破坏我程序的其余部分。

这是钩子:

const useInstitution = () => {
  const setCurrentId = useSetRecoilState(institutionId);
  const currentId = useRecoilValue(institutionId);

  console.log(currentId);
  // The above line properly logs the UUID I want
  
  const handleValues = useCallback((values: InstitutionFormType) => {
    
    return {
      ...values,institution_registered_number: values.institution_registered_number.replace(/\D+/g,''),institution_id: currentId || values.institution_id,};
  },[currentId]);

  const insertInstitution = useCallback(async (values,callback) => {
    const newValues = handleValues(values);
    const {
      institution_logo_file,} = newValues;
    const response = await createInstitution(newValues);
    setCurrentId(response?.data.institution_id);
  },[handleValues,setCurrentId]);

  const institutionEdit = useCallback(async (values,callback) => {
    const newValues = handleValues(values);
    console.log(currentId);
    // This line logs an empty value

  },[currentId,handleValues]);

  return {
    insertInstitution,institutionEdit,currentId,};
};

export default useInstitution;

这是原子:

export const institutionId = atom({
  key: 'institutionId',default: '',});

在这个钩子中,当 createInstitution 请求被调用并成功时,id 被设置为 Recoil Atom institutionId,我尝试将它登录到两个不同的一行,一根在函数外,一根在函数institutionEdit内,例如:

enter image description here

第一行是来自函数外部和钩子内部的console.log的日志。第二行是institutionEdit函数内的console.log。

为什么会这样?如何在钩子的函数中正确访问它?

解决方法

useSetRecoilState 文档指出

返回一个可以异步用来改变状态的setter函数。可以向 setter 传递一个新值或一个接收先前值作为参数的更新程序函数。

状态由 useSetRecoilState 返回的 setter 异步更改。为了在更新后的状态上执行某些操作,您应该使用 useEffect 来监视更改并运行所需的代码。

请看下面的例子。

const {
  useCallback,useEffect,useContext,} = React;
const {
  RecoilRoot,atom,useSetRecoilState,useRecoilValue
} = Recoil;

const institutionId = atom({
  key: 'institutionId',default: '',});

const createInstitution = () => new Promise(res => setTimeout(() => res({
  data: {
    institution_id: Math.round(Math.random() * 50)
  }
}),1500))

const useInstitution = () => {
  const setCurrentId = useSetRecoilState(institutionId);
  const currentId = useRecoilValue(institutionId);

  console.log(currentId);
  // The above line properly logs the UUID I want

  const handleValues = useCallback((values: InstitutionFormType) => {

    return {
      ...values,institution_registered_number: values.institution_registered_number.replace(/\D+/g,''),institution_id: currentId || values.institution_id,};
  },[currentId]);

  const insertInstitution = useCallback((values,callback) => {
    const newValues = handleValues(values);
    const {
      institution_logo_file,} = newValues;
    createInstitution(newValues).then(response =>
      setCurrentId(response && response.data.institution_id));
  },[handleValues,setCurrentId]);

  const institutionEdit = useCallback((values,callback) => {
    const newValues = handleValues(values);
    console.log(currentId);
    // This line logs an empty value

  },[currentId,handleValues]);

  return {
    insertInstitution,institutionEdit,currentId,};
};

const insts = new Array(10).fill().map((v,i) => ({
  institution_logo_file: 'logo 1',institution_registered_number: `reg no ${i}`
}))

const App = () => {
    const {
      insertInstitution,} = useInstitution();

    useEffect(() => {
      insertInstitution(insts[0])
    },[])

    // Getting the recoil state value
    const recoilValue = useRecoilValue(institutionId)
    useEffect(() => {
      institutionEdit(insts[0])
    },[institutionEdit,recoilValue]) // execute only when `recoilValue` changes
    console.log(recoilValue)

    return ( < div > Hi < /div>)
    }

    ReactDOM.render( < RecoilRoot > < App / > < /RecoilRoot>,document.querySelector('#root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/recoil@0.3.1/umd/recoil.min.js"></script>
<div id="root" />

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。