繁体   English   中英

如何使用Apollo 2使用GraphQL查询中的数据预填充表单?

[英]How to pre-fill a form with data from a GraphQL query using Apollo 2?

我很难将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);

这是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)

我目前使用的方法是即使数据尚不可用也始终呈现表单。 这样,装载道具就不需要检查,因为它假定所有数据都可用。 如果您确实检查了加载道具并且只在加载数据时呈现表单,那么客户端浏览器会等待显示表单直到数据可用,这可能会让人感到烦恼,尤其是当数据可用时间更长时。 最好让浏览器利用这个空闲时间在DOM中构建表单。

但是如何从graphql查询和prefill中了解初始状态?

状态用于保持表单输入数据,而来自graphql源的初始数据永远不会加载到状态! 每次需要(真值)数据时,都会重新计算。 这个重新计算应该只在一个地方进行,所以我引入了一个辅助函数getTruthData()。 无论你需要真值数据,你都可以通过这个辅助函数来处理它。 例如,渲染以及将更新的数据提交回graphql mutate。 并且只有在此getTruthData()函数中才需要根据可用性返回数据。 不要介意性能,因为重新计算真实数据真的很快,缓存只会因React重新渲染的性质而引入不可预测的结果。

我(试图)更新你的代码。 我做了什么:

  • 删除componentWillReceiveProps,因为它不需要
  • 删除渲染中的加载检查
  • 介绍getTruthData()
  • 从不受控制的形式变为受控制的形式(我后来注意到虽然与问题没有关系)

编码:

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以仅在正确加载数据时允许更改。 你甚至可以取消激活按钮的样式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM