如何在 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>;
};
我需要在 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>;
};