如何在 FormDataConsumer 中使用异步 javascript 函数,如 fetch

How can I use an asynchronous javascript function like fetch inside a FormDataConsumer

我需要在 FormDataConsumer 标签内使用 fetch,但 FormDataConsumer 似乎不支持异步函数。此代码对我不起作用:

<FormDataConsumer>
{
    async ({ formData, scopedFormData, getSource, ...rest }) => {
        return await fetch('/api/v1/attributes/'+scopedFormData.single_attributes_label)
        .then(res => res.json())
        .then(data => {
            console.log(JSON.stringify(data));
            //return JSON.stringify(data);
            resolve(JSON.stringify(data));
        });
        return JSON.stringify(scopedFormData);
    }
}
</FormDataConsumer>

我也检查了这个代码,这个也没有用:

async function getAttrItem(id) {
  return await fetch(`/api/v1/attributes/${id}`).then(response => response.json())
}

...

<FormDataConsumer>
{
    async ({ formData, scopedFormData, getSource, ...rest }) => {
        return await JSON.stringify(getAttrItem(scopedFormData.single_attributes_label));
    }
}
</FormDataConsumer>

但是当我使用这个时,它在控制台中工作:

<FormDataConsumer>
{
    ({ formData, scopedFormData, getSource, ...rest }) => {
        fetch('/api/v1/attributes/'+scopedFormData.single_attributes_label)
        .then(res => res.json())
        .then(data => {
            console.log(JSON.stringify(data));
            //return JSON.stringify(data);
            resolve(JSON.stringify(data));
        });
        return JSON.stringify(scopedFormData);
    }
}
</FormDataConsumer>

我是否应该使用这个 FormDataConsumer 填充一个对象,然后在另一个 FormDataConsumer 中检查该对象?

虽然您可以在 JSX 中使用 运行 JavaScript 表达式,但在 JSX 中使用过多 JavaScript 逻辑使其膨胀并不是一个好的模式。上述逻辑应该在 class 组件的 componentDidMount() 生命周期挂钩中处理,或者在功能组件的 useEffect 挂钩中处理。

在你的FormDataConsumer

componentDidMount() {
  fetch('/api/v1/attributes/'+scopedFormData.single_attributes_label)
    .then(res => res.json())
    .then(data => {
        console.log(data);
       // do the rest here
    });
}

useEffect(() => {
  fetch('/api/v1/attributes/'+scopedFormData.single_attributes_label)
    .then(res => res.json())
    .then(data => {
       console.log(data);
       // do the rest here
    });
 }, []);

你可能想做这样的事情:

const MyComponent = props => {
  const [data, setData] = useState();

  useEffect(() => {
    fetch("/api/v1/attributes/" + props.attribute)
      .then(res => res.json())
      .then(data => {
        setData(data);
      });
  }, [props.attribute]);

  if (!data) {
    return <someloadingindicator />;
  }

  // now you got your data. you can now return some component that uses the data here
};


// now in your component where using the FormDataConsumer
<FormDataConsumer>
  {({ formData, scopedFormData, getSource, ...rest }) => {
    return <MyComponent attribute={scopedFormData.single_attributes_label} />;
  }}
</FormDataConsumer>;

我的问题已通过以下代码解决:

<FormDataConsumer>
    {
        ({ formData, scopedFormData, getSource, ...rest }) => {
            return scopedFormData && formData && "type" in formData && <ReferenceInput label="Attribute Label" source={getSource('single_attributes_label')} reference={`attributes`} filter={{ document_type: formData.type }}>
            <AutocompleteInput optionText="title" optionValue="id" />
            </ReferenceInput>
        }
    }
</FormDataConsumer>
<FormDataConsumer>
    {
        ({ formData, scopedFormData, getSource, ...rest }) => {
            return "type" in formData && "single_attributes_label" in scopedFormData && <AttribValue source={getSource('single_attributes_value')} reference={`attributes`} filter={{ document_type: formData.type, id: scopedFormData.single_attributes_label, method: "getOptions" }} attribute={scopedFormData.single_attributes_label} {...rest} />
        }
    }
</FormDataConsumer>

const AttribValue = props => {
  const [data, setData] = useState();
  console.log('props', props);
  useEffect(() => {
    fetch("/api/v1/attributes/" + props.attribute)
      .then(res => res.json())
      .then(data => {
        setData({ data });
      });
  }, [props.attribute, props.label]);

  if (!data) {
    return 'Please Wait...';
  }
  let newProp = Object.assign({}, props, { label: "Attributes Value" });
  return data.data.attribute_type == 'multiselect' ? <ReferenceArrayInput {...newProp}><AutocompleteArrayInput optionText="text" optionValue="id" /></ReferenceArrayInput> : <ReferenceInput {...newProp}><AutocompleteInput optionText="text" optionValue="id" /></ReferenceInput>;
};