开发者问题收集

异步调用 React Hook

2022-03-22
91

抱歉,这是 React 初学者的问题。我正在尝试使用 React Hook 来获取数据并将其异步返回给组件。

    const CallSubmit = async () =>  {
        return await useSubmitForm(tenantForm, datasetForm, entityForm)
    }

    const CallSubmitHook = async () => {
        const submitStatus = await CallSubmit();
        console.log(submitStatus)
        if (submitStatus === true) {
            setCurrentForm(5)
        } else if (submitStatus === false) {
            setCurrentForm(6)
        }
    }

useSubmitForm 是我遇到问题的钩子。使用此代码迭代,我收到以下错误: 无效的钩子调用。钩子只能在函数组件的主体内调用。

我已将钩子调用移至另一个函数以尝试修复此错误,但错误仍然存​​在。如果它需要位于函数的顶层,那么在提交表单后,我该如何有条件地调用它?

我尝试将获取功能放入 useEffect 中,但问题是我需要获取功能在将其分配给变量之前取回其响应。请告诉我如何最好地实现这一点?

编辑 根据 Dave 的回答,我重组了我的代码。

Hook(抱歉,这里很复杂。需要使用数据进行 3 次单独的 api 调用):

export default async function useSubmitForm(tenant, dataset, entity) {

let tenantRequestParams = {}
let datasetRequestParams = {}
let entityRequestParams = {}

  const [isSending, setIsSending] = useState(false);
  const [formPostResult, setFormPostResult] = useState()
  const postFormData = async (tenant, dataset, entity) => {
    setIsSending(true);
    const result = await axios.get('token url')
    .then((res) => {
      token = res.data
  
      tenantRequestParams = {
        url: "api1",
        config: {
          headers: {
            'Access-Control-Allow-Origin': '*',
            'Authorization': `Bearer ${token}`,
          }
        },
        body: JSON.parse(tenant),
      };
    
      datasetRequestParams = {
        url: "api2",
        config: {
          headers: {
            'Access-Control-Allow-Origin': '*',
            'Authorization': `Bearer ${token}`,
          }
        },
        body: JSON.parse(dataset),
      };
    
      entityRequestParams = {
        url: "api3",
        config: {
          headers: {
            'Access-Control-Allow-Origin': '*',
            'Authorization': `Bearer ${token}`,
          }
        },
        body: JSON.parse(entity),
      };
    }).then(() => {
      console.log(tenantRequestParams.url,
        tenantRequestParams.body,
        tenantRequestParams.config)
  
      function postTenant() {
        return axios
        .post(
          tenantRequestParams.url,
          tenantRequestParams.body,
          tenantRequestParams.config
        )
        .then((res) => {
          console.log(res);
          return res;
        })
        .catch((error) => {
          console.error(error);
          return error;
        });
      }
  
      function postDataset() {
        return axios
        .post(
          datasetRequestParams.url,
          datasetRequestParams.body,
          datasetRequestParams.config
        )
        .then((res) => {
          console.log(res);
          return res;
        })
        .catch((error) => {
          console.error(error);
          return error;
        });
      }
  
      function postEntity() {
        return axios
        .post(
          entityRequestParams.url,
          entityRequestParams.body,
          entityRequestParams.config
        )
        .then((res) => {
          console.log(res);
          return res;
        })
        .catch((error) => {
          console.error(error);
          return error;
        });
      }
  
      axios.all([postTenant(), postDataset(), postEntity()])
        .then(res => {
          return res;
        }).catch(e => {
          console.error(e)
          return e;
        })
  
    });
    setFormPostResult(result)
  }
  const postFormDataCallback = useCallback(postFormData, [])

return { isSending, success: formPostResult, postFormData: postFormDataCallback };
}

以及来自组件(简化版本):

import useSubmitForm from '../hooks/useSubmitForm';

export default function FormPage(props) {
    const { isSending, success, postFormData } = useSubmitForm();
    const [tenantForm, setTenantForm] = useState('');
    const [datasetForm, setDatasetForm] = useState('');
    const [entityForm, setEntityForm] = useState('');

            return (
                <div>
                    <Form (3 forms, sets values for each to state above)/>
                    <PrimaryButton type="button" onClick={() => {
                        postFormData(tenantForm, datasetForm, entityForm)
                    }}>Submit</PrimaryButton>

                </div>
            )
}

使用此实现,我遇到一个问题,即组件中的解构无法正常工作(所有 3 个都是未定义的 any 值)。我这里遗漏了什么吗?

1个回答

钩子属于您功能组件的范围,必须始终以相同的顺序调用。

406786905

更新 在上面的示例中, useubmitform 是钩子。 (钩子以 使用 。)将钩子移至其所属的位置。不要将异步放在钩子前。这个想法是您调用钩子,在后台可以做一些工作。挂钩可以返回其他方法(例如,您可以在React组件中调用的PostTenantForm()。)

update2 这是一些非常粗糙的psudo代码。您需要阅读一些教程以跨越终点线,但这是轮廓。

412814876

Dave
2022-03-22