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