简体   繁体   English

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

[英]how to run functions after usestate is set and use the state value

I have a function that runs 2 async functions.我有一个运行 2 个异步函数的 function。 The first one needs to set the useState data so that the second one can use that data.第一个需要设置 useState 数据,以便第二个可以使用该数据。 Then I am trying to get that variable and pass it to a third function.然后我试图获取该变量并将其传递给第三个 function。 To pass state variables I am using npm use-between , which works like useState.为了传递 state 变量,我使用了 npm use-between ,它的工作方式类似于 useState。 However, I am having trouble getting and passing the variables.但是,我无法获取和传递变量。

between.js -之间.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 -创建.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};   
}

Which is being called in another component in a different file -在不同文件的另一个组件中调用它 -

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
    };

Right now the functions are returning undefined.现在函数返回未定义。 From my understanding this is because how useState works, and it doesn't show the value 'til the next render.据我了解,这是因为 useState 是如何工作的,直到下一次渲染它才会显示该值。 So I'm unsure on how to achieve my goal?所以我不确定如何实现我的目标?

Based on the code suggested by @ilketorun, I modified my code and added more to illustrate further -根据@ilketorun 建议的代码,我修改了我的代码并添加了更多内容以进一步说明 -

between.js之间.js

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

create.js创建.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;

Then I try running it in another component -然后我尝试在另一个组件中运行它 -

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

hash is returning undefined and I'm unable to get the finalHash in the NextFunction hash 返回未定义,我无法在 NextFunction 中获取NextFunction

You can utilize useState and useEffect hooks.您可以利用useStateuseEffect挂钩。 useEffect will be re-rendered with respect to its dependencies. useEffect 将根据其依赖项重新渲染。 For example:例如:

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])

decouple concerns解耦关注点

Create a myapi module that handles your get/post requests and returns appropriate responses.创建一个处理您的 get/post 请求并返回适当响应的myapi模块。 Coordinating multiple requests and setting state should be a separate concern -协调多个请求和设置 state 应该是一个单独的问题 -

// 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 }

These ~15 lines of code effectively replace the entirety of your ~50 lines create.js file.这约 15 行代码有效地替换了整个约 50 行create.js文件。

Now inside your component -现在在您的组件内 -

import * as myapi from "./myapi"

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

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

useValues appears incorrect useValues 显示不正确

In your useValues hook, you are wrapping setHash and setFinalHash in useCallback -在您的useValues挂钩中,您将setHashsetFinalHash包装在useCallback -

  1. The set* function returned from useState is already a "callback".useState返回的set* function 已经是一个“回调”。 There's no need to memoize it.没有必要记住它。
  2. The functions you create do not pass arguments to the set* functions.您创建的函数不会将 arguments 传递给set*函数。 This is evident by setHash() and setFinalHash() which have no arguments.没有 arguments 的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
  }
}

Should be changed to -应改为——

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

Which begs the question, do you even need this?这引出了一个问题,你甚至需要这个吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM