设置usestate后如何运行函数并使用状态值

问题描述 投票:0回答:2

我有一个运行 2 个异步函数的函数。第一个需要设置 useState 数据,以便第二个可以使用该数据。然后我尝试获取该变量并将其传递给第三个函数。为了传递状态变量,我使用 npm use- Between ,它的工作原理类似于 useState。但是,我在获取和传递变量时遇到问题。

Between.js -

import { useState, useCallback } from 'react'
import { useBetween } from 'use-between';

const useValues = () => { 
    
    const [hash, setHash] = useState(false);
    const [finalHash, setFinalHash] = useState(false);
    const sH = useCallback(() => setHash(), []);
    const sFH = useCallback(() => setFinalHash(), []);
  
    return {
      hash,
      finalHash,
      sH,
      sFH
    };
  };
  
  export const useSharedValues = () => useBetween(useValues);

create.js -

    import { useState, useCallback } from 'react';
    import { useSharedValues } from './utils/between';
    import FormData from 'form-data';
    import axios from 'axios';
    
    function useCreate() {  
    const {
    hash,
    finalHash,
    sH,
    sFH } = useSharedValues();
           
        async function create1() {
 myCanvas.toBlob(async function(blob) { // extra function I run to get an image then upload file
                await axios({
                     method: "post",
                     url: "url",
                 }).then((response) => {
                   sH(response.data.Hash); // trying to set state here
                 });
})
        }
       
    async function create2() {      
        var objects = [
               {
                   "hash": hash, // trying to use state in next function
               }
        ]
       
       var data = JSON.stringify(objects)
          
       await axios({
           method: "post",
           url: "url",
           data: data,
       }).then((response) => {
       sFH(response.data.IpfsHash); // set final hash to use in 3rd function
       })
       }
       
    const create = useCallback(async () => {
        await create1(); 
        await create2(); // run after create1 has finished
        console.log(finalHash);
    }, [create1, create2]);
       
    return {create};   
}

在不同文件的另一个组件中调用它 -

import useCreate from "../create.js";

const {create} = useCreate();

    const onPressed = async () => {
    await create();
    await The3rdFunction(); // 3rd function needs to wait for final hash variable so it can use it
    };

现在函数返回未定义。根据我的理解,这是因为 useState 的工作原理,并且它在下一次渲染之前不会显示该值。所以我不确定如何实现我的目标?

根据@ilketorun建议的代码,我修改了代码并添加了更多内容以进一步说明 -

Between.js

....
const sH = useCallback((event) => setHash(event.target.value), []);
...

create.js

 function useCreate() {
        const {
            aSharedValue,
          } = useSharedValues();
    
    async function create1() {
        ....
        canvas.toBlob(async function(blob) { // here I upload a file which gives me the hash when done
            const formData = new FormData();
            formData.append('file', blob);
          
              return axios({
              method: "post",
              url: "url",
              data: formData,
              headers: { ... },
          }).then(res => res.data.Hash);
          
          });
    
    }
    
    async function create2(hash) { 
        var objects = [
            {
                "hash": hash,
                "value": aSharedValue
            }
        ]
    
    var data = JSON.stringify(objects)
    
    return axios({
        method: "post",
        url: "url",
        data: data,
        headers: { .... },
    }).then(res => res.data.Hash)
    }
    
    async function create3() {
      const hash = await create1()
      const finalHash = await create2(hash)
      return {hash, finalHash}
    }
    
    return { create1, create2, create3 }
    }
    
    export default useCreate;

然后我尝试在另一个组件中运行它 -

const onPressed = async () => {  
const finalHash = await create3()
const { success } = NextFunction(finalHash);
}

hash 返回未定义,我无法在

NextFunction

中获取 FinalHash
reactjs react-hooks async-await
2个回答
1
投票

解耦顾虑

创建一个

myapi
模块来处理您的 get/post 请求并返回适当的响应。协调多个请求和设置状态应该是一个单独的问题 -

// myapi.js
import axios from "axios"

function create1() {
  return axios.post("url").then(res => res.data.Hash)
}

function create2(hash) {
  return axios.post("url", {hash}).then(res => res.data.IpfsHash)
}

async function create3() {
  const hash = await create1()
  const finalHash = await create2(hash)
  return {hash, finalHash}
}

export { create1, create2, create3 }

这 ~15 行代码有效地替换了整个 ~50 行

create.js
文件。

现在在你的组件内部 -

import * as myapi from "./myapi"

function MyComponent(...) {
  // ...

  useEffect(_ => {
    myapi.create3()
      .then(({hash, finalHash}) => {
        setHash(hash)
        setFinalHash(finalHash)
      })
      .catch(console.error)
  }, [])
}

useValues 出现错误

useValues
挂钩中,您将
setHash
setFinalHash
包裹在
useCallback
-

  1. set*
    返回的
    useState
    函数已经是一个“回调”。不需要记住它。
  2. 您创建的函数不会将参数传递给
    set*
    函数。
    setHash()
    setFinalHash()
    没有参数,这一点很明显。
const useValues = () => { 
  const [hash, setHash] = useState(false)
  const [finalHash, setFinalHash] = useState(false)
  const sH = useCallback(() => setHash(), [])       // <-
  const sFH = useCallback(() => setFinalHash(), []) // <-
  return {
    hash,
    finalHash,
    sH,
    sFH
  }
}

应改为-

const useValues = () => {
  const [hash, setHash] = useState(false)
  const [finalHash, setFinalHash] = useState(false)
  return {
    hash,
    finalHash,
    sH: setHash,       // <--
    sFH: setFinalHash  // <--
  }

这就引出了一个问题,你真的需要这个吗?


0
投票

您可以使用

useState
useEffect
挂钩。 useEffect 将根据其依赖项重新呈现。例如:

const [myFirstState,setMyFirstState] = useState()
const [mySecondState,setMySecondState] = useState()

useEffect(()=> {
  const myAsyncFunc = async () => {
    // await something here
    let awaitedResult = await someFunction();
    setMyFirstState(awaitedResult)
  }
  myAsyncFunc();
},[])

useEffect(()=> {
  // do stuff with myFirstState
  const myOtherAsyncFunc = async () => {
    // await something here
    let awaitedOtherResult = await someOtherFunction();
    setMySecondState(awaitedOtherResult)
  }
  myOtherAsyncFunc();
},[myFirstState])

useEffect(()=> {
  // do stuff with mySecondState
},[mySecondState])
© www.soinside.com 2019 - 2024. All rights reserved.