4

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?

2
  • What version of react-admin are you using? Commented Jan 3, 2020 at 14:55
  • 1
    react-admin v2.9.9 was used in my project Commented Jan 5, 2020 at 8:05

3 Answers 3

3

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>;
Sign up to request clarification or add additional context in comments.

Comments

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
    });
 }, []);

2 Comments

Thanks, I knew about componentDidUpdate but I didn't want to use that. In somehow, using useEffect was my question.
@MasoudILDEREMI sorry, I mean componentDidMount, not componentDidUpdate.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.