我有一个运行 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
解耦顾虑
创建一个
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
- 中
set*
返回的 useState
函数已经是一个“回调”。不需要记住它。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 // <--
}
这就引出了一个问题,你真的需要这个吗?
您可以使用
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])