我很难将Apollo 2 GraphQL查询中的数据转换为常规表单字段。
其他人如何接近这个?以前尝试过Relay,并成功使用组件构造函数设置表单字段状态。
然而,在阿波罗,即使在搜索了几个小时并阅读了大量文档后,我仍然处于黑暗中......
在组件初始化期间,状态始终返回null,因为在稍后阶段设置了props。我试着在加载后设置它,但这让我陷入无休止的循环......
我完全迷失了:/
这就是我现在想出来的......它有效。但这是否是推荐的方法来满足这一要求?
import React from 'react';
import { Route, Redirect, Switch } from "react-router-dom";
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
// SEMANTIC-UI REACT
import { Container, Form, Button, Loader, Message } from "semantic-ui-react";
const MY_QUERY = gql`
query {
erp(id:"RXJwTm9kZToy") {
id
name
code
}
}`;
class Test extends React.Component {
constructor(props) {
super(props)
this.state = {
}
}
componentWillReceiveProps(newProps) {
if (newProps !== this.props) {
this.setState({
erp_name: (newProps.data.erp || "").name,
erp_code: (newProps.data.erp || "").code
});
}
}
render() {
if (this.props.data.loading) {
return <Loader active inline='centered' />;
} else if (this.props.data.error) {
return <Message error content={this.props.data.error.message} />;
} else {
return (
<Form>
<ul>
<li key={this.props.data.erp.id}>{this.props.data.erp.name}</li>
</ul>
<Form.Input name="erp_name" label="ERP Name" placeholder="Name" value={this.state.erp_name} />
<Form.Input name="erp_code" label="ERP Code" placeholder="Code" value={this.state.erp_code} />
<Button type='submit'>Submit</Button>
</Form>
);
}
}
}
export default graphql(MY_QUERY)(Test);
答案 0 :(得分:0)
这是React和ReduxForm的一个小例子。 也许这会对你有帮助。
在此示例中,查询将在组件初始化时执行,并将返回填写表单所需的数据。
我希望它可以帮到你!
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { compose } from 'recompose'
import { graphql, withApollo, gql } from 'react-apollo'
import { Form } from 'redux-form'
class MyExampleComponent extends Component {
render() {
const { userData } = this.props
return (
<Form
initialValues={userData}
/>
)
}
}
MyExampleComponent.propTypes = {
userData: PropTypes.object
}
const query = gql`
query getUser($userId: ID) {
user(id: $userId) {
age
firstName
lastName
}
}
`
export default compose(
withApollo,
graphql(query, {
props: ({ data }) => ({
isLoading: data.loading,
userData: data.user
}),
options: ({ params }) => ({
variables: { id: params.id }
})
})
)(MyExampleComponent)
答案 1 :(得分:0)
我当前使用的方法是始终渲染表单,即使数据尚不可用。这样,由于假定所有数据都可用,因此不需要检查加载道具。如果您确实检查加载道具并仅在数据加载后才呈现表单,则客户端浏览器将等待显示表单,直到数据可用为止,这可能会令人烦恼,尤其是当数据可用时间更长时。最好让浏览器利用这些空闲时间在DOM中建立表单。
但是如何通过graphql查询和预填充了解初始状态?
该状态用于保留表单输入数据,而从未将来自graphql源的初始数据加载到该状态中!每次需要(真实)数据时,都会重新计算。这种重新计算应该只在一个地方发生,因此我引入了一个辅助函数getTruthData()。在任何需要使用真相数据的地方,都可以通过此辅助函数对其进行处理。例如。渲染,并将更新后的数据提交回graphql mutate。而且仅在此getTruthData()函数中,才需要根据可用性返回数据。不必在意性能,因为重新计算真实数据的速度确实非常快,并且由于React重新渲染的特性,缓存只会引入不可预测的结果。
我(已尝试)更新您的代码。我做了什么:
代码:
class Test extends React.Component {
constructor(props) {
super(props);
this.getProfileTruth = this.getProfileTruth.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
getTruthData() {
return {
erp_id: this.props.data.erp.id || '',
erp_name: this.state.erp_name || this.props.data.erp.name || '',
erp_code: this.state.erp_code || this.props.data.erp.code || '',
};
// OR you might want to use the underscore helper for larger forms with more fields to keep like this:
return _.defaults(
{},
this.state,
this.props.data.erp,
{ erp_name: '', erp_code: '' },
);
}
handleChange(data) {
this.setState(data);
}
handleSubmit(e) {
e.preventDefault();
const { erp_id, erp_name, erp_code } = this.getProfileTruth();
// run a mutate on graphql
}
render() {
const { erp_id, erp_name, erp_code } = this.getProfileTruth();
return (
<Form>
<ul>
<li key={erp_id}>{erp.name}</li>
</ul>
<Form.Input
name="erp_name"
label="ERP Name"
placeholder="Name"
value={erp_name}
onChange={e => this.handleChange({ erp_name: e.target.value })} />
<Form.Input
name="erp_code"
label="ERP Code"
placeholder="Code"
value={erp_code}
onChange={e => this.handleChange({ erp_code: e.target.value })} />
<Button type='submit' onClick={this.handleSubmit}>Submit</Button>
</Form>
);
}
}
副作用可能是,如果来自graphql的数据要花费很长时间,则该表格已经可以输入。使用受控表单,您可以检入handleChange以仅在正确加载数据时才允许更改。您甚至可以取消激活按钮的样式。