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

╄→гoц情女王★ 提交于 2020-02-24 04:35:10

问题


I need to use a fetch inside the FormDataConsumer tag but it seems FormDataConsumer does not support async functions. This code didn't work for me:

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

I also checked this code and this one also didn't work:

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>

But when I use this one, it works in the console:

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

Should I use this FormDataConsumer for filling an object and then inside the other FormDataConsumer check the object?


回答1:


You might wanna do something like this:

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



回答2:


While you can run JavaScript expressions in JSX, it is not a good pattern to bloat it with too much JavaScript logic within JSX. The above logic should be handled within the componentDidMount() lifecycle hook for class components, or in the useEffect hook, for functional components.

In your FormDataConsumer

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

or

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



回答3:


My issue was fixed with this code:

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


来源:https://stackoverflow.com/questions/59528291/how-can-i-use-an-asynchronous-javascript-function-like-fetch-inside-a-formdataco

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!