将选定值传递给 Get 请求

Pass Selected Values to a Get request

我的目标是将表单中选择的值传递给 get 请求。

请求应如下所示,在 valuessubmit 之后。

get(api/csv/pets/?columns=DOG&columns=CAT&columns=FISH)

onSubmit={async (values, { resetForm }) => {
    alert(JSON.stringify(values, null, 2));
    setCsvData(values);
    console.log(csvData);  
    const getCsvFile = async (values) => {
      try {
        const { data } = await fetchContext.authAxios.get(
          `/api/csv/pets/${id}/?columns=${csvData ? csvData + '&' : null}`, values);
    
        toCsv(data);
      } catch (err) {
        console.log(err);
      }
    };
    getCsvFile();

然而,即使 formik 接受了一个值的有效负载,当我将它放在 csvDatasetCsvData(values) 中时我仍然得到未定义。

如何获取查询中选择的值,并采用所需的格式?

我的数据:

export const CheckList = [
  {
    id: 'column-dog',
    label: 'Dog',
    value: 'DOG',
    name: 'column',
  },
  {
    id: 'column-cat',
    label: 'Cat',
    value: 'CAT',
    name: 'column',
  },
  {
    id: 'column-turtle',
    label: 'Turtle',
    value: 'TURTLE',
    name: 'column',
  },
  {
    id: 'column-fish',
    label: 'Fish',
    value: 'FISH',
    name: 'column',
  },
]

我的表格:

const [csvData, setCsvData] = useState([]);
const selectAllData = CheckList.map((checkbox) => checkbox.value);


return (
     <Formik
        initialValues={{
           columns: [],
           selectAll: false,
        }}
        onSubmit={async (values, { resetForm }) => {
          alert(JSON.stringify(values, null, 2));
          setCsvData(values);
          console.log(csvData);
          resetForm();
        }}
        >
         {({ values, setFieldValue }) => (
           <Form>
            <div>
              <Field
                onChange={() => {
                  if (!values.selectAll) {
                    setFieldValue('columns', selectAllData);
                  } else {
                    setFieldValue('columns', []);
                  }
                  setFieldValue('selectAll', !values.selectAll);
                }}
                checked={values.selectAll}
                type="checkbox"
                name="selectAll"
              />{' '}
              Select All
            </div>
    
          {CheckList.map((checkbox) => (
            <div key={checkbox.value}>
              <label>
                <Field
                  type="checkbox"
                  name="columns"
                  value={checkbox.value}
                 />{' '}
                 {checkbox.label}
               </label>
             </div>
           ))}
    
          <button
            className="btn"
            type="submit"
            download
          >
            DOWNLOAD CSV
          </button>
        </Form>
      )}
    </Formik>
)

您不能在异步函数中使用 setState,因为 setState 本身就是一个异步函数,它不是 return 承诺。因此,我们不能将 async/await 用于 setState 方法。(如果不可能使其成为 await,则状态更改将立即触发undefined 值而不是设置给定值)

更多信息请参考:https://iamsongcho.medium.com/is-setstate-async-b1947fbb25e5

因此,最好的用例是从 onSubmit() 函数中删除 async 以使其同步。因此,setState 将异步触发组件中的状态更改。

然后在表格重置后保留 getCsvFile(values),因为您已经这样做了。并将 getCsvFile() 函数保留在组件外部,因为它不会进行任何与状态相关的更改。

      onSubmit={(values, { resetForm }) => {
        alert(JSON.stringify(values, null, 2));
        setCsvData(values);
        console.log(csvData);
        resetForm();

        getCsvFile(); // this function will trigger asynchronously
      }}

我认为您的代码过于复杂了。从状态中删除 csvData,而是将 values 传递到请求中。

onSubmit={async (values, { resetForm }) => {
    const getCsvFile = async () => {
      try {
        const { data } = await fetchContext.authAxios.get(
          `/api/csv/pets/${id}/?columns=${values ? values + '&' : null}`, values);
        toCsv(data);
      } catch (err) {
        console.log(err);
      }
    };
    getCsvFile();
}

您遇到错误是因为请求在 csvData 设置之前触发。 setState 是异步的:)